在完成了 Go 后端的硬核逻辑后,压力来到了前端。Mole 的前端并没有复杂的全家桶,而是回归本质,将精力集中在与 Wails 3 的运行时(Runtime)交互上。
本文将重点拆解:前端如何调用后端服务,以及如何处理“激励视频”这种跨端异步逻辑。
一、 桥梁:引入运行时与绑定
在 Wails 3 中,前端不再需要通过 HTTP 接口访问后端,而是通过自动生成的 Bindings。在 main.js 中,这几行代码是整个应用的灵魂:
import { Events, Browser } from "@wailsio/runtime";
// 由 Wails 3 自动生成的绑定代码
import {
HandleStopFrp,
HandleStartFrp,
GetDomainURL,
} from "../bindings/mole/MoleService";
Events: 核心组件,用于监听后端的主动推送到前端的消息(如日志、状态变更)。
HandleStartFrp 等: 它们看起来是 JS 函数,但执行时会直接触发 Go 后端对应 Service 的方法。
二、 核心实战:扫码激励的异步闭环
Mole 的核心业务是“看广告换带宽”。这就带来一个挑战:用户点击“连接”后,由于没看广告,流程会中断并弹出小程序码。前端如何知道用户什么时候看完了广告?
- 拦截与判断
我们不能在前端写 if(adWatched),因为前端代码是透明的。逻辑必须在 Go 后端:如果后端判断该用户需要看广告,HandleStartFrp 会返回特定的状态码(如 2)。 - 状态机:从“连接中”到“等待验证”
看看这段核心的 connect 逻辑:
async function connect() {
const hint = document.getElementById("hint");
try {
const res = await HandleStartFrp(); // 发起 Go 调用
if (res.code === 1) {
// 情况 A: 验证通过,直接分配域名并连接
document.getElementById("subdomain-url").innerText = res.content;
setUIConnected(true);
addLog("成功连接到服务器", "system");
} else if (res.code === 2) {
// 情况 B: 触发激励逻辑,弹出小程序码
showAdModal(res.content); // res.content 包含小程序码 Base64 或 URL
addLog("请扫码完成验证后继续", "info");
// 【关键】注册一次性监听事件,等待后端“发令枪”
const unsubscribe = Events.On("ad-status", (data) => {
closeAdModal(); // 关闭弹窗
unsubscribe(); // 销毁监听,防止重复触发
if (data.status === "done") {
addLog("验证成功,正在连接...", "system");
connect(); // 再次发起连接请求,此时后端将通过验证
} else {
// 处理异常(如超时、未看完)
hint.innerText = data.message;
hint.classList.add("error-shake");
addLog(`验证未完成: ${data.message}`, "error");
setUIConnected(false);
}
});
}
} catch (err) {
setUIConnected(false);
}
}
三、 为什么这样设计?(经验总结)
- 安全性(Security First):
连接逻辑的“入场券”完全由 Go 后端控制。前端只是一个 UI 展示层,即便用户强行修改 JS 调用 connect(),如果后端没有收到广告系统的回调信号,依然不会分配 frp 配置。 - 订阅-发布模式(Events):
使用 Events.On 而不是轮询(Polling)。当用户在手机上看完广告,后端 API 收到微信的回调后,会通过 app.Emit(“ad-status”, …) 通知前端。这种实时性让用户体验非常丝滑——手机看完,电脑屏幕上的弹窗瞬间自动消失并连接。 - UI 细节:单页面布局(Zero-Config UI):
由于 Mole 的界面追求极致精简,所有的 CSS 样式、HTML 布局和 JS 逻辑都高度集成在 index.html 和 main.js 中。对于这类工具软件,减少资源加载链比追求组件化更重要。
四、 结语
前端在 Wails 3 项目中扮演的是 “状态反馈器” 的角色。通过 Bindings 调用 Go 方法,通过 Events 监听实时动态。
至此,Mole 客户端从“为何而生”到“后端驱动”再到“前端交互”的开发逻辑已经全部分享完毕。这种 “桌面工具 + 小程序生态” 的模式,为个人开发者如何平衡“服务器成本”与“用户体验”提供了一个全新的思路。
如果你也想开发一款轻量级的桌面工具,Wails 3 绝对是 2026 年最值得尝试的选择!