├── .gitattributes ├── .gitignore ├── .npmrc ├── .prettierrc ├── LICENSE ├── README.md ├── babel.config.js ├── images ├── 20220619224349.png ├── 20220619224729.png ├── 20220628140513.png ├── 20220628140530.png └── 20220727224540308.png ├── package.json ├── public ├── favicon.ico ├── icon.ico ├── index.html └── static │ └── theme.less ├── src ├── App.vue ├── assets │ ├── font │ │ ├── font.ttf │ │ └── iconfont.css │ ├── logo.png │ └── robots.png ├── background.js ├── components │ ├── Header.vue │ ├── IPAddress.vue │ └── Side.vue ├── config │ └── index.js ├── main.js ├── router │ └── index.js ├── theme │ ├── cus-theme.less │ ├── js │ │ └── theme.js │ └── variables.less └── views │ ├── Dashboard.vue │ ├── Net.vue │ └── Setting.vue ├── vue.config.js └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist_electron 4 | /dist 5 | /dist_electron 6 | 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | 12 | # Log files 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | pnpm-debug.log* 17 | 18 | # Editor directories and files 19 | .idea 20 | .vscode 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry =https://registry.npm.taobao.org 2 | ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ 3 | ELECTRON_BUILDER_BINARIES_MIRROR=http://npm.taobao.org/mirrors/electron-builder-binaries/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": true, 4 | "singleQuote": true, 5 | "printWidth": 175, 6 | "semi": true, 7 | "trailingComma": "none", 8 | "bracketSpacing": true, 9 | "arrowParens": "avoid", 10 | "htmlWhitespaceSensitivity": "ignore" 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 jackchou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 串口调试助手 2 | 3 | > Electron + Vue + node-serialport + Ant Design 实现串口调试助手 4 | 5 | ## 功能 6 | 7 | - [x] 串口通信 8 | - [x] 16 进制发送和显示 9 | - [x] 自动刷新串口列表 10 | - [x] 定时发送信息 11 | - [x] TCP 通信 12 | - [x] UDP 通信 13 | - [x] UDP 通信 14 | - [x] 主题色切换 15 | 16 | ## 下载&&运行 17 | 18 | 点击[下载链接](https://github.com/binkzhou/vue3_serial/releases) 19 | 20 | ## 界面预览 21 | 22 | ![image-20220123183755272](./images/20220619224729.png) 23 | 24 | ![image-20220123183916062](./images/20220619224349.png) 25 | 26 | ![image-20220123183916062](./images/20220628140513.png) 27 | 28 | ![image-20220123183916062](./images/20220628140513.png) 29 | 30 | ![image-20220123183916062](./images/20220628140530.png) 31 | 32 | ![image-20220727224540308](./images/20220727224540308.png) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"], 3 | }; 4 | -------------------------------------------------------------------------------- /images/20220619224349.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/images/20220619224349.png -------------------------------------------------------------------------------- /images/20220619224729.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/images/20220619224729.png -------------------------------------------------------------------------------- /images/20220628140513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/images/20220628140513.png -------------------------------------------------------------------------------- /images/20220628140530.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/images/20220628140530.png -------------------------------------------------------------------------------- /images/20220727224540308.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/images/20220727224540308.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-serial", 3 | "version": "0.1.0", 4 | "private": true, 5 | "main": "background.js", 6 | "scripts": { 7 | "lint": "vue-cli-service lint", 8 | "build": "vue-cli-service electron:build", 9 | "serve": "node src/theme/js/theme.js && vue-cli-service electron:serve", 10 | "postinstall": "electron-rebuild;electron-builder install-app-deps", 11 | "postuninstall": "electron-builder install-app-deps" 12 | }, 13 | "dependencies": { 14 | "ant-design-vue": "^2.2.8", 15 | "antd-theme-generator": "^1.2.11", 16 | "core-js": "^3.6.5", 17 | "electron": "12", 18 | "iconv-lite": "^0.6.3", 19 | "less": "2.7.3", 20 | "less-loader": "7.3.0", 21 | "serialport": "^9.2.0", 22 | "vue": "^3.2.6", 23 | "vue-router": "^4.0.12" 24 | }, 25 | "devDependencies": { 26 | "@vue/cli-plugin-babel": "~4.5.0", 27 | "@vue/cli-plugin-eslint": "~4.5.0", 28 | "@vue/cli-service": "~4.5.0", 29 | "@vue/compiler-sfc": "^3.0.0", 30 | "babel-eslint": "^10.1.0", 31 | "electron-devtools-installer": "3.2.0", 32 | "electron-rebuild": "^3.2.2", 33 | "eslint": "^6.7.2", 34 | "eslint-plugin-vue": "^7.0.0", 35 | "vue-cli-plugin-electron-builder": "^2.1.1" 36 | }, 37 | "eslintConfig": { 38 | "root": true, 39 | "env": { 40 | "node": true 41 | }, 42 | "extends": [ 43 | "plugin:vue/vue3-essential", 44 | "eslint:recommended" 45 | ], 46 | "parserOptions": { 47 | "parser": "babel-eslint" 48 | }, 49 | "rules": {} 50 | }, 51 | "browserslist": [ 52 | "> 1%", 53 | "last 2 versions", 54 | "not dead" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/public/favicon.ico -------------------------------------------------------------------------------- /public/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/public/icon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 14 | 15 | 16 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | 23 | 34 | -------------------------------------------------------------------------------- /src/assets/font/font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/src/assets/font/font.ttf -------------------------------------------------------------------------------- /src/assets/font/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'iconfont'; 3 | /* Project id 2546196 */ 4 | src: url('./font.ttf') format('truetype'); 5 | } 6 | 7 | .iconfont { 8 | font-family: 'iconfont' !important; 9 | font-size: 16px; 10 | font-style: normal; 11 | -webkit-font-smoothing: antialiased; 12 | -moz-osx-font-smoothing: grayscale; 13 | } 14 | 15 | .icon-wangluo:before { 16 | content: '\e617'; 17 | } 18 | 19 | .icon-jiekou:before { 20 | content: '\e638'; 21 | } 22 | 23 | .icon-zuixiaohua:before { 24 | content: '\e650'; 25 | } 26 | 27 | .icon-github:before { 28 | content: '\e645'; 29 | } 30 | 31 | .icon-Close:before { 32 | content: '\e689'; 33 | } 34 | 35 | .icon-window-maximize:before { 36 | content: '\e679'; 37 | } 38 | .icon-shezhi:before { 39 | content: '\e64b'; 40 | } 41 | .icon-duihao:before { 42 | content: '\eaf1'; 43 | } 44 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/robots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binkzhou/vue3_serial/5bb504466c0bdb916ebf6227a66be58a554c302f/src/assets/robots.png -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { app, protocol, BrowserWindow, ipcMain } from 'electron'; 4 | import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'; 5 | import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer'; 6 | const isDevelopment = process.env.NODE_ENV !== 'production'; 7 | 8 | // Scheme must be registered before the app is ready 9 | protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }]); 10 | let win; 11 | async function createWindow() { 12 | // Create the browser window. 13 | win = new BrowserWindow({ 14 | width: 900, 15 | height: 580, 16 | minWidth: 900, 17 | minHeight: 580, 18 | useContentSize: false, 19 | frame: false, 20 | show: false, 21 | webPreferences: { 22 | // Use pluginOptions.nodeIntegration, leave this alone 23 | // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info 24 | nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, 25 | contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION 26 | } 27 | }); 28 | 29 | if (process.env.WEBPACK_DEV_SERVER_URL) { 30 | // Load the url of the dev server if in development mode 31 | await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL); 32 | if (!process.env.IS_TEST) win.webContents.openDevTools(); 33 | } else { 34 | createProtocol('app'); 35 | // Load the index.html when not in development 36 | win.loadURL('app://./index.html'); 37 | } 38 | 39 | win.on('ready-to-show', function () { 40 | win.show(); // 初始化后再显示 41 | }); 42 | } 43 | app.allowRendererProcessReuse = false; 44 | // Quit when all windows are closed. 45 | app.on('window-all-closed', () => { 46 | // On macOS it is common for applications and their menu bar 47 | // to stay active until the user quits explicitly with Cmd + Q 48 | if (process.platform !== 'darwin') { 49 | app.quit(); 50 | } 51 | }); 52 | 53 | app.on('activate', () => { 54 | // On macOS it's common to re-create a window in the app when the 55 | // dock icon is clicked and there are no other windows open. 56 | if (BrowserWindow.getAllWindows().length === 0) createWindow(); 57 | }); 58 | 59 | // This method will be called when Electron has finished 60 | // initialization and is ready to create browser windows. 61 | // Some APIs can only be used after this event occurs. 62 | app.on('ready', async () => { 63 | if (isDevelopment && !process.env.IS_TEST) { 64 | // Install Vue Devtools 65 | try { 66 | await installExtension(VUEJS3_DEVTOOLS); 67 | } catch (e) { 68 | console.error('Vue Devtools failed to install:', e.toString()); 69 | } 70 | } 71 | createWindow(); 72 | }); 73 | 74 | // Exit cleanly on request from parent process in development mode. 75 | if (isDevelopment) { 76 | if (process.platform === 'win32') { 77 | process.on('message', data => { 78 | if (data === 'graceful-exit') { 79 | app.quit(); 80 | } 81 | }); 82 | } else { 83 | process.on('SIGTERM', () => { 84 | app.quit(); 85 | }); 86 | } 87 | } 88 | 89 | app.on('window-all-closed', () => { 90 | if (process.platform !== 'darwin') { 91 | app.quit(); 92 | } 93 | }); 94 | ipcMain.on('window-close', function () { 95 | win.close(); 96 | }); 97 | 98 | ipcMain.on('window-min', function () { 99 | win.minimize(); 100 | }); 101 | 102 | ipcMain.on('window-max', function () { 103 | if (win.isMaximized()) { 104 | win.unmaximize(); 105 | } else { 106 | win.maximize(); 107 | } 108 | }); 109 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 19 | 37 | 98 | -------------------------------------------------------------------------------- /src/components/IPAddress.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 143 | 203 | -------------------------------------------------------------------------------- /src/components/Side.vue: -------------------------------------------------------------------------------- 1 | 20 | 29 | 30 | 70 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 3 | * @date 2022-01-12 4 | * @author tudou 5 | * @lastModify tudou 2022-01-12 6 | */ 7 | const serialConfig = { 8 | baudRate: [115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800], // 波特率 9 | parity: ['none', 'even', 'mark', 'odd', 'space'], // 校验位 10 | dataBits: [8, 7, 6, 5], // 数据位 11 | stopBits: [1, 2] // 停止位 12 | }; 13 | 14 | export default serialConfig; 15 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import router from './router'; 3 | import App from './App.vue'; 4 | import ant, { message } from 'ant-design-vue'; 5 | import 'ant-design-vue/dist/antd.less'; 6 | // import 'ant-design-vue/dist/antd.css'; 7 | import '@/assets/font/iconfont.css'; 8 | const app = createApp(App); 9 | app.config.globalProperties.$message = message; 10 | app.use(ant); 11 | app.use(router); 12 | app.mount('#app'); 13 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHashHistory } from 'vue-router'; 2 | import Dashboard from '../views/Dashboard.vue'; 3 | import Net from '../views/Net.vue'; 4 | import Setting from '../views/Setting.vue'; 5 | 6 | const routes = [ 7 | { 8 | path: '/', 9 | name: 'Dashboard', 10 | component: Dashboard 11 | }, 12 | { 13 | path: '/net', 14 | name: 'Net', 15 | component: Net 16 | }, 17 | { 18 | path: '/setting', 19 | name: 'Setting', 20 | component: Setting 21 | } 22 | ]; 23 | 24 | const router = createRouter({ 25 | history: createWebHashHistory(), 26 | routes 27 | }); 28 | 29 | export default router; 30 | -------------------------------------------------------------------------------- /src/theme/cus-theme.less: -------------------------------------------------------------------------------- 1 | //自定义的样式+用到了variables里面的变量+ant的主题样式都可以用 2 | .ant-layout-header { 3 | background-color: @header-back-color; 4 | 5 | .header-item:hover { 6 | background-color: @header-item-hover-color; 7 | } 8 | } 9 | .nav_active { 10 | color: @primary-color !important; 11 | } 12 | -------------------------------------------------------------------------------- /src/theme/js/theme.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const { generateTheme } = require('antd-theme-generator'); 5 | //生成的theme.less文件的位置 6 | const outputFilePath = path.join(__dirname, '../../../public/static/theme.less'); 7 | //自定义样式 8 | const cusCssFilePath = path.join(__dirname, '../cus-theme.less'); 9 | 10 | generateTheme({ 11 | //node_modules中antd的路径 12 | antDir: path.join(__dirname, '../../../node_modules/ant-design-vue'), 13 | //styles对应的目录路径,需要和下面的variables.less在一个文件夹 14 | stylesDir: path.join(__dirname, './src'), 15 | //less变量的入口文件,variables.less里面定义的变量,必须在themeVariables里面定义 16 | varFile: path.join(__dirname, '../variables.less'), 17 | //您要动态更改的变量列表 18 | themeVariables: ['@primary-color', '@header-item-hover-color', '@header-back-color'], 19 | outputFilePath: outputFilePath, 20 | customColorRegexArray: [/^fade\(.*\)$/] 21 | }) 22 | .then(() => { 23 | console.log('配置主题成功'); 24 | //自定义样式与ant主题样式合并 25 | //读取提取过的ant样式 26 | const themeCss = fs.readFileSync(outputFilePath).toString(); 27 | // //读取自定义的CSS 28 | const cusCss = fs.readFileSync(cusCssFilePath).toString(); 29 | fs.writeFileSync(outputFilePath, themeCss + cusCss); 30 | //重新覆盖themeCss 31 | console.log(`🌈 主题覆盖成功. OutputFile: ${outputFilePath}`); 32 | }) 33 | .catch(() => { 34 | console.log('配置主题失败'); 35 | }); 36 | -------------------------------------------------------------------------------- /src/theme/variables.less: -------------------------------------------------------------------------------- 1 | //插件默认主题变量+这些变量必须在themejs里面定义好 2 | @primary-color: #1890ff; // 全局主色 3 | //自定义样式 4 | @header-item-hover-color: blue; //头部项浮动颜色 5 | @header-back-color: #1890ff; //头部底色 6 | @nav-bg: #f3f5f6; 7 | @nav-font-color: rgba(0, 0, 0, 0.85); 8 | @nav-hover-color: #fafafa; 9 | @border-color: #ddd; 10 | @center-bg: #ffffff; 11 | @ant-nav-header: #ffffff; 12 | -------------------------------------------------------------------------------- /src/views/Dashboard.vue: -------------------------------------------------------------------------------- 1 | 81 | 251 | 420 | -------------------------------------------------------------------------------- /src/views/Net.vue: -------------------------------------------------------------------------------- 1 | 75 | 358 | 552 | -------------------------------------------------------------------------------- /src/views/Setting.vue: -------------------------------------------------------------------------------- 1 | 13 | 35 | 67 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | pluginOptions: { 3 | electronBuilder: { 4 | nodeIntegration: true, 5 | externals: ['serialport'], 6 | builderOptions: { 7 | productName: '串口调试助手', 8 | win: { 9 | icon: 'public/icon.ico', 10 | artifactName: '${productName}-${version}.${ext}', 11 | target: [ 12 | { 13 | target: 'nsis', 14 | arch: ['x64'] 15 | } 16 | ] 17 | }, 18 | dmg: { 19 | contents: [ 20 | { 21 | x: 410, 22 | y: 150, 23 | type: 'link', 24 | path: '/Applications' 25 | }, 26 | { 27 | x: 130, 28 | y: 150, 29 | type: 'file' 30 | } 31 | ] 32 | }, 33 | linux: { 34 | icon: 'build/electron-icon/icon.png', 35 | target: 'AppImage' 36 | }, 37 | mac: { 38 | icon: 'build/electron-icon/icon.icns' 39 | }, 40 | nsis: { 41 | oneClick: false, 42 | allowElevation: true, 43 | allowToChangeInstallationDirectory: true, 44 | installerIcon: 'public/icon.ico', 45 | uninstallerIcon: 'public/icon.ico', 46 | installerHeaderIcon: 'public/icon.ico', 47 | createDesktopShortcut: true, 48 | createStartMenuShortcut: true 49 | } 50 | } 51 | } 52 | } 53 | }; 54 | --------------------------------------------------------------------------------