- 删除通用 desktop target,重命名 platform targets 为简短形式 (desktop-mac/win/linux)
- 构建产物文件名统一为 nex-{os}-{arch}[.exe] 格式
- Windows 托盘图标使用 .ico 格式(运行时按平台选择)
- Windows 原生对话框使用 user32.MessageBoxW 替代 msg * 命令
- 更新 README.md 和 package-macos.sh 中的引用
- 添加单元测试覆盖 MessageBoxW 封装和图标选择逻辑
- 同步更新 desktop-app spec 规范文档
3.8 KiB
3.8 KiB
Context
Nex 桌面应用是一个将后端服务(Go/Gin)与前端静态资源(embed.FS)打包为单一可执行文件的跨平台应用。当前 Windows 构建存在三类问题:
- 通用
desktoptarget 无平台感知:输出build/nex无.exe后缀,且缺少-H=windowsguilinker flag 导致控制台窗口闪现 - 系统托盘图标加载失败:
getlantern/systray在 Windows 上期望 ICO 格式,代码传入了 64x64 的 PNG showError/showAbout使用msg *:Windows Home 版本可能不可用,配合-H=windowsgui后行为不可预测,且不支持自定义标题栏
项目已有 assets/icon.ico(256x256)但代码未使用。
Goals / Non-Goals
Goals:
- Windows 构建产物可直接双击运行(.exe 后缀、无控制台窗口)
- 系统托盘图标在所有平台上正确加载
- Windows 上使用原生
MessageBoxW对话框替代msg * - Makefile target 命名简洁统一
Non-Goals:
- 不引入新的第三方依赖
- 不改变 macOS/Linux 上的现有行为
- 不涉及应用签名或代码公证(属于发布流程)
- 不重构整体打包架构
Decisions
1. 删除通用 desktop target,重命名平台 target
决策:删除 desktop target,将 desktop-darwin/desktop-windows/desktop-linux 重命名为 desktop-mac/desktop-win/desktop-linux。
理由:通用 target 在跨平台构建时必然需要条件判断,增加复杂度。按平台分离更明确,且项目已有先例。短命名 win/mac/linux 更简洁。
产物命名统一:nex-{os}-{arch}[.exe]
nex-mac-arm64、nex-mac-amd64nex-win-amd64.exenex-linux-amd64
2. 托盘图标运行时按平台选择格式
决策:在 setupSystray 中根据 runtime.GOOS 选择图标文件:
- Windows:加载
assets/icon.ico(256x256 ICO) - 其他:加载
assets/icon.png(PNG)
备选方案:
Build tags + 编译时选择:增加文件数,维护成本高所有平台统一用 ICO:Linux/macOS 的 systray 实现对 ICO 支持不一致
理由:运行时判断最简单,两个文件都已通过 embedfs.Assets(assets/*)嵌入,零额外成本。
3. Windows 原生对话框使用 user32.MessageBoxW
决策:通过 syscall 调用 user32.dll 的 MessageBoxW,替换 msg *。
实现方式:
var (
user32 = syscall.NewLazyDLL("user32.dll")
procMessageBoxW = user32.NewProc("MessageBoxW")
)
func messageBox(title, message string) {
procMessageBoxW.Call(0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(message))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))), 0x10)
}
备选方案:
继续用:不解决 Home 版不可用、标题栏不支持的问题msg *:同样不可靠rundll32调用引入:引入重依赖,过度lxn/walk等 GUI 库
理由:MessageBoxW 是 Windows 原生 API,所有版本都有,与 -H=windowsgui 完美兼容,支持标题栏和图标类型,零依赖。使用 syscall(非 unsafe 外部依赖)即可。
4. showError/showAbout 统一用平台 switch
决策:保持现有的 switch runtime.GOOS 结构,仅替换 Windows 分支实现。macOS(osascript)和 Linux(zenity)不变。
Risks / Trade-offs
- [syscall 跨架构]
MessageBoxW的syscall.NewLazyDLL仅在 Windows 上有效 → 使用runtime.GOOS守卫,非 Windows 不会执行该路径,编译时通过 build 文件或运行时判断确保不触发 - [ICO 嵌入体积]
icon.ico270KB,已在embedfs中,不增加新体积 → 无风险 - [Makefile 兼容性] 删除
desktoptarget 后,CI/本地脚本如果引用它需更新 → 需检查是否有外部引用