引入electron,electron-builder,vue-cli-plugin-electron-builder,electron-devtools
npm i --save-dev electron
1,引入之后在package.json 文件下会自动生成
image.png2,在vue-cli 项目src下 创建background.js
代码如下:
import { app, protocol, BrowserWindow, ipcMain, Menu, dialog, globalShortcut } from 'electron'
import {
createProtocol
} from "vue-cli-plugin-electron-builder/lib";
const fs = require("fs") //引入node原生fs模块
const os = require("os")
const isDevelopment = process.env.NODE_ENV !== "production";
let mainWindow
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: "app", privileges: { secure: true, standard: true } }
]);
const path = require('path')
const menus = [{
label: '视图',
submenu: [{
label: '刷新',
role: 'reload'
},
{
label: '退出',
role: 'quit'
}]
}]
const menu = Menu.buildFromTemplate(menus)
function createWindow () {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false,
webPreferences: {
enableRemoteModule: true, // 允许弹框
webSecurity: false,
nodeIntegration: true,
nodeIntegrationInWorker: true, // 在Web工作器中启用了Node集成
preload: path.join(__dirname, 'preload.js'),
defaultEncoding: 'utf-8'
}
})
mainWindow.once('ready-to-show', () => {
mainWindow.show()
})
if (process.env.WEBPACK_DEV_SERVER_URL) { // 开发环境
// Load the url of the dev server if in development mode
mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) mainWindow.webContents.openDevTools();
globalShortcut.register('CommandOrControl+Shift+i', function () { // 使用快捷键shift+ctrl+i 调起开发工具
mainWindow.webContents.openDevTools()
})
} else { // 生产环境
// mainWindow.webContents.openDevTools() // 生产环境关闭调试工具
// Load the index.html when not in development
createProtocol('app')
// Load the index.html when not in development
mainWindow.loadURL('app://./index.html')
}
Menu.setApplicationMenu(menu)
}
/**
* 初始化
*/
app.whenReady().then(() => {
createWindow()
app.setAppUserModelId('管理平台')
// 点击MacOS底部菜单时重新启动窗口
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
// 兼容MacOS系统的窗口关闭功能
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
mainWindow = null
})
// 最小化窗口(自定义导航条时)
ipcMain.on('window-min', () => {
mainWindow.minimize()
})
// 最大化窗口(自定义导航条时)
ipcMain.on('window-max', () => {
// 如果已经是最大化窗口就还原
if (mainWindow.isMaximized()) {
mainWindow.restore();
} else {
mainWindow.maximize()
}
})
// 关闭窗口
ipcMain.on('window-close', () => {
mainWindow.close()
mainWindow = null;
app.exit();
})
// 主进程给进程通信
ipcMain.on('toMain', function (event, arg) {
event.sender.send('fromMain', arg); // 返回给渲染进程
});
// 下载进程
ipcMain.on('downLoad', function (event, arg) {
mainWindow.webContents.downloadURL(arg.url);
});
// 调用文件读入方法
ipcMain.on('judgeUse', function (event, arg) {
// 读入文件
// 异步返回
fs.readFile("./authorize.bin", { encoding: "utf-8" }, (err, data) => {
// if (err) {
// // dialog.showMessageBox({
// // type: 'error',
// // title: '找不到authorize.bin文件',
// // message: err.path,
// // buttons: ['ok']
// // }).then((index) => {
// // if (index.response === 0) {
// // mainWindow.close()
// // mainWindow = null;
// // app.exit();
// // }
// // })
// event.sender.send('fromMain', null); // 返回给渲染进程
// } else {
// event.sender.send('fromMain', data); // 返回给渲染进程
// }
event.reply('authorizeBack', data); // 返回给渲染进程
})
});
// 读取本地服务的IP 地址 同步
ipcMain.on('syncGetLocalServer', function (event, arg) {
// 读入文件,同步返回数据
fs.readFile("./localServer.xml", { encoding: "utf-8" }, (err, data) => {
event.returnValue=data; // 返回给渲染进程
})
});
// 读取本地服务的IP 地址 异步
ipcMain.on('asyncGetLocalServer', function (event, arg) {
// 读入文件
// 异步返回
fs.readFile("./localServer.xml", { encoding: "utf-8" }, (err, data) => {
event.reply('asyncBackLocalServer', data); // 返回给渲染进程
})
});
//隐藏按钮
ipcMain.on('hideMenu', function (event, arg) {
mainWindow.setMenu(null);
});
//显示按钮
ipcMain.on('showMenu', function (event, arg) {
mainWindow.setMenu(menu);
});
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === "win32") {
process.on("message", data => {
if (data === "graceful-exit") {
app.quit();
}
});
} else {
process.on("SIGTERM", () => {
app.quit();
});
}
}
3,在vue-cli 项目src下 创建 preload.js(预加载文件)
import { contextBridge, ipcRenderer } from 'electron'
window.ipcRenderer = ipcRenderer
contextBridge.exposeInMainWorld('ipcRenderer', {
// 异步向主进程 发送消息
send: (channel, data) => {
let validChannels = ['toMain', 'downLoad', 'judgeUse', 'hideMenu', 'showMenu', 'window-close', 'asyncGetLocalServer']
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data)
}
},
// 同步向主进程 发送消息,
sendSync: (channel, data) => {
let validChannels = ['syncGetLocalServer']
if (validChannels.includes(channel)) {
return ipcRenderer.sendSync(channel, data)
}
},
// 异步接收主进程返回的数据
receive: async (channel) => {
let validChannels = ['authorizeBack', 'asyncBackLocalServer']
if (validChannels.includes(channel)) {
return new Promise((resolve) => {
ipcRenderer.on(channel, (event, ...args) => {
resolve(...args)
})
});
}
}
})
4,在package.json 里面添加 background.js 的引入
"main": "background.js",
image.png
5, 在package.json =>scripts添加electron的启动、打包命令
"electron:build": "vue-cli-service electron:build",
"electron:serve": "vue-cli-service electron:serve",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps"
image.png
package.json 最终配置如下:
{
"name": "mine-exe",
"author": {
"name": "xd"
},
"description": "test",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "vue-cli-service serve -open",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"electron:build": "vue-cli-service electron:build",
"electron:serve": "vue-cli-service electron:serve",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps"
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"axios": "^0.21.1",
"core-js": "^3.6.5",
"dayjs": "^1.10.4",
"echarts": "^5.1.0",
"electron-builder": "^22.11.1",
"element-ui": "^2.15.1",
"js-md5": "^0.7.3",
"vue": "^2.6.11",
"vue-cli-plugin-electron-builder": "^2.0.0",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"main": "background.js",
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"electron": "^12.0.7",
"electron-devtools-installer": "^3.2.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
}
}
6,在vue.config.js 里的配置如下
const path = require('path')
const resolve = dir => path.join(__dirname, dir)
const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpack = require('webpack')
const BASE_URL = process.env.NODE_EVN === 'production'
? './'
: './'
const port = process.env.PORT || 8080
module.exports = {
publicPath: BASE_URL,
outputDir: 'mine-exe',
assetsDir: 'static',
lintOnSave: process.env.NODE_ENV === 'development',
// 这里写你调用接口的基础路径,来解决跨域,如果设置了代理,那你本地开发环境的axios的baseUrl要写为 '' ,即空字符串
devServer: {
// proxy: 'localhost:3000'
port,
open: false
},
pluginOptions: {
electronBuilder: {
removeElectronJunk: false,
preload: './src/preload.js',
builderOptions: {
"appId": "com.example.app",
"productName": "智慧矿山管理平台",//项目名,也是生成的安装文件名,即aDemo.exe
"copyright": "Copyright © 2021",//版权信息
"directories": {
"output": "build"//输出文件路径
},
"win": {//win相关配置
"icon": "./src/assets/icon.ico",//图标,当前图标在根目录下,注意这里有两个坑
"target": [
{
"target": "nsis",//利用nsis制作安装程序
"arch": [
"x64",//64位
]
}
]
},
"nsis": {
"oneClick": false, // 是否一键安装
"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
"allowToChangeInstallationDirectory": true, // 允许修改安装目录
"installerIcon": "./src/assets/icon.ico",// 安装图标
"uninstallerIcon": "./src/assets/icon.ico",//卸载图标
"installerHeaderIcon": "./src/assets/icon.ico", // 安装时头部图标
"createDesktopShortcut": true, // 创建桌面图标
"createStartMenuShortcut": true,// 创建开始菜单图标
"shortcutName": "mine", // 图标名称
},
}
},
},
chainWebpack: config => {
config.resolve.alias
.set('@', resolve('src'))
config.entry('polyfill').add('@babel/polyfill')
},
css: {
loaderOptions: {
sass: {
prependData: `
@import "@/styles/variables.scss";
@import "@/styles/mixins.scss";
`
}
}
},
// 设为false打包时不生成.map文件
productionSourceMap: true
}
7,在终端里使用“npm run electron:serve ” 即可打开本地EXE程序
8 在终端里使用“npm run electron:build ” 即可打包本地EXE程序:(注意有坑)
打包本地程序解决下载依赖过慢的方法如下:
https://www.jianshu.com/p/5d8ea14ce374
9 最终vue-cli 项目目录如下
红色箭头指的文件是新增的,绿色箭头指向的文件为要修改的
image.png
网友评论