场景
electron和h5文件分离
需求
-
electron部分添加配置h5URL页面
通过配置winURL
(h5的路径)打开最终渲染页面,给electron部分增加一个默认页(与electron同级src下的404页面)用来输入winURL
。这里添加两种检验:①通过fetch网络状态判断winURL
是否有效,②通过electron的隐藏窗口触发send
事件。 -
本地配置文件
通过electron提供的app.getPath('documents')
获取用户的目录路径,在这个路径下写入验证成功的winURL
,每次进入electron都先在本地检查下是否有该配置文件,在有配置文件情况下,获取文件内winURL
,然后检验该winURL
是否还有效,若无效则返回配置URL页面,反之进入渲染页面。
electron部分

- 配置URL404页面中保存按钮的方法

envCheck
为electron创建的事件这里用于初始化 winURL
<template>
<div class="container flex-row-start">
<div class="problemBox flex-col">
<img class="logo" src="/images/common/company.png" />
<div v-if="curUrlState == URLState.noelectron" class="tip flex-row">请勿使用非法客户端访问服务</div>
<div v-if="curUrlState == URLState.input || curUrlState == URLState.isSuccess" class="url-input flex-row">
<input v-model="urlValue" placeholder="请输入有效服务地址" />
<div class="save flex-row" @click="saveUrl">
保存
</div>
</div>
<div class="tip2" v-if="curUrlState == URLState.input && !isInvalid">
无效地址,请检查地址</div>
<div class="tip2" v-if="curUrlState == URLState.isSuccess">
请输入正确的测绘渲染地址</div>
<el-text v-loading="loading" element-loading-text="Loading..." />
</div>
</div>
</template>
<script lang="ts" setup>
import {
onMounted, ref } from "vue";
enum URLState {
loading = '0',
noelectron = '1',
input = '2',
isSuccess = '3'
};
const curUrlState = window.location.hash.split('=')?.[1];
const loading = ref(curUrlState == URLState.loading);
const isInvalid = ref(true);//输入的url是否有效
const urlValue = ref('');
onMounted(() => {
isInvalid.value = true;
urlValue.value = '';
})
function saveUrl() {
if (!urlValue.value) return;
loading.value = true;
// 检查url是否有效
fetch(urlValue.value)
.then(response => {
loading.value = false;
if (response.ok) {
console.log('Path is correct');
isInvalid.value = true;
//@ts-ignore
window.api.send("envCheck", {
url: urlValue.value });
} else {
console.error('Path is incorrect');
isInvalid.value = false;
}
})
.catch(() => {
loading.value = false;
isInvalid.value = false;
});
}
</script>
- electron下的main.ts
let winURL = "http://localhost:5173/"; // 默认配置URL页面的路径
let mainWin;
let checkWin;
let timer; //返回输入url页面的计时器
//404?status=0是包含loading的页面
//404?status=2是只包含url输入框
//404?status=3是包含url输入框和错误渲染地址提示
/* 打开主窗体 */
const createMainWindow = () => {
mainWin = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
//@ts-ignore
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
nodeIntegrationInWorker: true,
webSecurity: false,
preload: path.join(__dirname, "preload.ts"),
},
title: 测试",
show: false,
});
mainWin.loadURL(winURL);
mainWin.webContents.openDevTools(); //调试工具
mainWin.once("ready-to-show", () => {
mainWin.show();
mainWin.maximize();
});
};
// 创建隐藏验证渲染窗口进程
const createcheckWindow = () => {
checkWin = new BrowserWindow({
webPreferences: {
//@ts-ignore
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
nodeIntegrationInWorker: true,
webSecurity: false,
preload: path.join(__dirname, "preload.ts"),
},
show: false, // 设置为 false,不显示窗口
});
checkWin.loadURL(winURL);
};
app.whenReady().then(() => {
mainWin = null;
checkWin = null;
checkConfigFile().then((res) => {
createMainWindow();
mainWin.loadURL("http://localhost:5173/#/404?status=0");
});
});
// 检查配置文件
function checkConfigFile() {
// 要检查的文件路径
const filePath = path.join(app.getPath("documents"), "mk_config.txt");
return new Promise((resolve) => {
// 检查文件是否存在
fs.access(filePath, fs.constants.F_OK, (err) => {
if (!err) {
// 文件已经存在
console.log("File already exists.");
//读取文件内容
fs.readFile(filePath, "utf8", (err, data) => {
if (err) {
console.error("Error reading file:", err);
resolve(false);
} else {
console.log("File content:", data);
//验证配置文件里的路径
if (data) {
winURL = data;
// 打开检验进程,去checkWinOpenSuccess看是否正常执行
createcheckWindow();
// 10s之后如果检验没反应,返回默认页
timer = setTimeout(() => {
mainWin.loadURL("http://localhost:5173/#/404?status=3");
checkWin = null;
}, 10000);
}
resolve(true);
}
});
} else {
resolve(false);
}
});
});
}
// 写入配置文件
function createAndWriteConfig(data) {
const filePath = path.join(app.getPath("documents"), "mk_config.txt");
fs.writeFile(filePath, data, (err) => {
if (err) {
console.error("Error writing file:", err);
} else {
console.log("File created and content written.");
}
});
}
//校验权限,html是否在electron内打开和初始化winURL
const envCheck = (event, res) => {
console.log("envCheck", res);
if (res && res.url) {
winURL = res.url;
mainWin.loadURL("http://localhost:5173/#/404?status=0");
// 打开检验进程,去checkWinOpenSuccess看是否正常执行
createcheckWindow();
// 10s之后如果检验没反应,返回默认页
timer = setTimeout(() => {
mainWin.loadURL("http://localhost:5173/#/404?status=3");
checkWin = null;
}, 10000);
}
event.reply("envCheckCallback", {
result: true,
});
};
ipcMain.on("envCheck", envCheck);
// 校验渲染进程路径是否可以正常打开
const checkWinOpenSuccess = (event) => {
console.log("checkWinOpenSuccess", winURL);
if (checkWin) {
// 检验成功,写入地址
createAndWriteConfig(winURL);
mainWin.loadURL(winURL);
}
clearTimeout(timer);
checkWin = null;
};
ipcMain.on("checkWinOpenSuccess", checkWinOpenSuccess);
- 与electron同级下默认页面入口文件main.ts
(1)envCheck
这里用于验证electron环境
(2)checkWinOpenSuccess
用于给electron部分发送信息,验证electron部分输入的url
是正确的
router.beforeEach((to, from, next) => {
//校验是否在electron的环境中
try {
//@ts-ignore
window.api.send("envCheck", {
test: 11 });
//@ts-ignore
window.api.receive("envCheckCallback", (res: boolean) => {
if (!res) return;
if (to.path == "/") {
next("/404?status=2");
} else {
// 当前hash路径status为0或3时(0:输入url,3:提示无效路径),需要刷新页面
const isLoading =
from.fullPath == "/404?status=2" &&
to?.query &&
to?.query?.status == "0";
const isInvalid =
from.fullPath == "/404?status=0" &&
to?.query &&
to?.query?.status == "3";
if (isLoading || isInvalid) {
window.location.reload();
}
next();
}
});
} catch (error) {
if (to.path == "/") {
next("/404?status=1");
} else {
next();
}
}
});
winURL下H5
- 入口文件main.ts
(1)envCheck
这里用于验证electron环境
(2)checkWinOpenSuccess
用于给electron部分发送信息,验证electron部分输入的url
是正确的
router.beforeEach((to, from, next) => {
try {
//@ts-ignore
window.api.send("envCheck");//发给electron,envCheckCallback接收成功表示在electron的环境中
//@ts-ignore
window.api.send("checkWinOpenSuccess");
//@ts-ignore
window.api.receive("envCheckCallback", (res: boolean) => {
if (!res) return;
next();
});
} catch (error) {
if (to.path == "/") {
next("/warn");
} else {
next();
}
}
});
注意:
(1)envCheck
同方法不同作用, 在404页面的savaUrl
方法中用于初始化winURL
,在两个main.ts中是验证是否在electron环境
(2)在electron切换地址只能通过hash模式,history模式找不到路径,同时在全局路由守卫需要通过判断to,from控制hash刷新