最近,一个之前做的electron桌面应用,需要增加两个功能;第一是读取本地的配置文件,然后记载配置文件中的ip地址;第二就是增加缩放功能;
第一,配置本地文件
首先需要在vue工程根目录中,新建一个config.json文件;如下图
config.json内容如下:
javascript
{
"ip": "1.11.21.219",
"port": 30002,
}
然后在vue.config.js中需要排除这个文件,如下:
javascript
// 添加electron - app -icon
pluginOptions: {
electronBuilder: {
builderOptions: {
productName: 'xxxx', //项目名,也是生成的安装文件名
//copyright: "Copyright © 2019",//版权信息
win: {
icon: './public/favicon.ico',
// 以管理员权限运行
requestedExecutionLevel: 'requireAdministrator',
target: [{
target: "nsis", //利用nsis制作安装程序
arch: [
"x64", //64位
]
}],
},
nsis: {
oneClick: false, // 是否一键安装
allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
allowToChangeInstallationDirectory: true, // 允许修改安装目录
installerIcon: "./public/favicon.ico", // 安装图标
uninstallerIcon: "./public/favicon.ico", //卸载图标
installerHeaderIcon: "./public/favicon.ico", // 安装时头部图标
createDesktopShortcut: true, // 创建桌面图标
createStartMenuShortcut: true, // 创建开始菜单图标
shortcutName: "MIES", // 图标名称
},
directories: {
output: "./MIES_SETUP" //输出文件路径
},
/**** 注意这里 配置config.json ****/
extraResources: [
{ "from": "./config.json", "to": "../" }
],
},
nodeIntegration: true,
preload: 'src/preload.js'
}
},
//
然后,安装桌面应用之后,会在安装目录出现这个配置好的config.json.
第二,读取本地配置文件,创建window
在backgroundjs中,使用nodejs的fs模块读取根目录下的config.json文件,动态获取配置的ip和端口,然后创建window。
代码如下:
javascript
............
// Create the browser window.
let win = null;
async function createWindow() {
// 读取信息
var exePath = path.dirname(app.getPath("exe")).replace(/\\/g, "/");
// console.log(exePath);
var configPath = `${exePath}/config.json`;
var sockets = [];
// ******************** 这里是主要功能 ************************* //
// 读取本地文件 获取配置信息
fs.readFile(configPath, "utf-8", async (err, data) => {
if (data) {
const cp = require("child_process");
let res = JSON.parse(data);
const PAGE_URL = `https://${res.ip}:${res.port}`;
// 创建窗口
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
// process.env.ELECTRON_NODE_INTEGRATION
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: path.join(__dirname, "/preload.js"),
webSecurity: false,
allowRunningInsecureContent: false,
//zoomFactor: 0.6,
},
icon: path.join(__dirname, "./favicon.ico"),
});
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);
console.log("PAGE_URL ----- ", PAGE_URL);
await win.loadURL(PAGE_URL);
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(path.join(__dirname, "./index.html"));
// https://www.electronjs.org
console.log("PAGE_URL ----- ", PAGE_URL);
win.loadURL(PAGE_URL);
}
//进入软件即开启全屏
//win.setFullScreen(true);
// 最大化
win.maximize();
//配置ESC键退出全屏 ESC
globalShortcut.register("Alt+CommandOrControl+Q", () => {
win.setFullScreen(false);
});
// 配置设置快捷键
globalShortcut.register("Alt+CommandOrControl+S", () => {
win.webContents.send("asynchronous-message", "123");
});
// ctrl_alt_f 打开全屏设置
globalShortcut.register("Alt+CommandOrControl+F", () => {
win.setFullScreen(true);
});
// 主进程缩小窗口
ipcMain.on("window-min", function() {
// 收到渲染进程的窗口最小化操作的通知,并调用窗口最小化函数,执行该操作
win.minimize();
});
// ctrl_alt_i 手动打开开发者工具
globalShortcut.register("Alt+CommandOrControl+I", () => {
win.webContents.openDevTools({
mode: "bottom",
});
});
// 获取安装地址
// globalShortcut.register('Alt+CommandOrControl+P', () => {
// win.webContents.send("asynchronous-message", path.dirname(app.getPath('exe')));
// })
// 手动打开开发者工具
// ipcMain.on('open-dev', function () { // 收到渲染进程的窗口最小化操作的通知,并调用窗口最小化函数,执行该操作
// win.webContents.openDevTools({
// mode: 'bottom'
// })
// })
// 设置顶部菜单
// 自定义一些菜单
const appMenuTemplate = [
{
label: "窗口",
submenu: [
{
label: "打开全屏",
click: () => {
win.setFullScreen(true);
},
},
{
label: "退出全屏",
click: () => {
win.setFullScreen(false);
},
},
],
},
{
label: "设置",
submenu: [
// {
// label: "设置首页",
// click: () => {
// win.webContents.send("asynchronous-message", "123");
// },
// },
{
label: "强制刷新",
role: "forceReload",
},
{
label: "退出",
role: "quit",
},
{
label: "开发者选项",
click: () => {
win.webContents.openDevTools({
mode: "bottom",
});
},
},
],
},
];
const menu = Menu.buildFromTemplate(appMenuTemplate);
Menu.setApplicationMenu(menu);
// 窗口关闭的监听
win.on("closed", (event) => {
win = null;
});
// 点击关闭
win.on("close", (event) => {
const closeWinFlagValue = dialog.showMessageBoxSync(win, {
type: "info",
buttons: ["最小化到托盘", "直接退出", "取消"],
title: "提示",
message: "确定要退出吗?",
defaultId: 0,
cancelId: 2,
});
console.log("closeWinFlagValue", closeWinFlagValue);
event.preventDefault();
if (closeWinFlagValue === 0) {
// 托盘对象
var appTray = null;
// 系统托盘右键菜单
var trayMenuTemplate = [
{
label: "显示",
click: function() {
!win.isVisible() ? win.show() : null;
},
},
{
label: "退出",
click: function() {
app.quit();
},
},
];
win.hide();
// 系统托盘图标目录 path.join(__static, './logo_1.ico')
let trayIcon = path.join(__dirname, "./favicon.ico");
appTray = new Tray(trayIcon);
// 图标的上下文菜单
const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
// 设置此托盘图标的悬停提示内容
appTray.setToolTip("上海局高铁机务管理智能评价系统");
// 设置此图标的上下文菜单
appTray.setContextMenu(contextMenu);
// 单击击托盘显示隐藏
appTray.on("click", () => {
win.isVisible() ? win.hide() : win.show();
// 关闭托盘显示
appTray.destroy();
appTray = null;
});
} else if (closeWinFlagValue === 1) {
app.exit();
} else if (closeWinFlagValue === 2) {
win.focus();
win.show();
}
});
// 设置托盘
// Exit cleanly on request from parent process in development mode.
if (process.platform === "win32") {
/* process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
}) */
} else {
process.on("SIGTERM", () => {
app.quit();
});
}
// D:/dev_tools/MIES
//console.log('读取本地文件 == ', res);
// let socketPath = exePath + "/WebMiddleware.exe";
// //let child = cp.spawn(socketPath, [res.ip, res.port])
// cp.exec(`${socketPath} ${res.ip} ${res.port}`, (err, stdout, stderr) => {
// console.log("err, stdout, stderr", err, stdout, stderr);
// });
// 向vue发送配置的wsip和端口
let ws_path = `wss://${res.ws_ip}:${res.ws_port}`;
const http = require("http"); // 创建服务器对象
const server = http.createServer();
const closeServer = () => {
sockets.forEach(function(socket) {
socket.destroy();
});
server.close(function() {
console.log("close server!");
});
};
server.listen(res.local_port); // 对错误进行捕获
server.on("error", (err) => {
if (err.code == "EADDRINUSE") {
// 如果目标端口被占用将使用
// NodeJS 随机分配的端口号
server.listen(0);
}
}); // 在成功监听后,向终端输出被监听的端口号
server.on("listening", () => {
console.log(
"【HTTP Server is running at http://127.0.0.1:" +
server.address().port +
" 】"
);
});
server.on("connection", function(socket) {
sockets.push(socket);
//console.log('sockets', sockets);
socket.once("close", function() {
sockets.splice(sockets.indexOf(socket), 1);
});
});
server.on("request", function(req, res) {
const url = req.url;
if (url === "/getWsPath") {
res.setHeader("content-type", "application/json");
res.end(ws_path);
closeServer();
} else {
res.writeHeader(404);
res.end("404 not found");
closeServer();
}
});
}
});
}
至此就可以完成读取本地文件,获取配置信息功能。
第三,完成缩放功能
需求要求实现和浏览器一样,ctrl加上鼠标滚轮,可以完成页面的缩放,具体代码如下:
javascript
let level = 0;
// 缩放
win.webContents.on('zoom-changed',(e, zoomDirection)=>{
if (zoomDirection === 'in') {
level = level >= 3 ? level : level += 0.2
} else {
level = level <= -3 ? level : level -= 0.2
}
win.webContents.setZoomLevel(level)
})