# 整合启动器 + GM 管理工具 单 EXE 的 DNF90 启动器,内置完整 GM 管理工具(角色管理、道具发放、邮件、背包装备、拍卖行、任务、副本、钱包点券、删档等)。 ## 技术栈 - **Python 3.15**(32 位)+ **pywebview 6.x**(Edge WebView2 内嵌窗口) - 纯标准库 HTTP 后端 + 原生 HTML/CSS/JS 前端 - **PyInstaller** 打包单文件 EXE ## 文件说明 | 文件 | 说明 | |------|------| | `server.py` | 整合后端(启动器 + GM 工具,纯标准库) | | `db.py` | SQLite 数据访问层(删角色/删档/疲劳/物品名缓存) | | `native.py` | Native API 客户端(完整 GM 端点) | | `index.html` / `style.css` / `app.js` | 双视图前端 | | `DNF90启动器.spec` | PyInstaller 打包配置 | | `sponsor.png` / `sponsor_qr.png` | 赞助二维码 | | `qr/` | 关于页二维码(alipay / wechat / gzh / qq,可被 exe 同目录的同名文件覆盖) | | `启动器日志.txt` | 运行日志(运行时生成,exe 同目录,超过 512KB 转 `.old.txt`) | ## 运行时约定 - **单实例**:命名互斥量 `Local\DNF90Launcher-5E9C1B7A`,重复启动只会把已有窗口提到前台 - **多调用模式**:`DNF90启动器.exe [args]` 会用 `runpy` 直接执行该脚本。打包后 `sys.executable` 就是 exe 自己,`start_gmweb()` 正是靠这条路径拉起 `gmweb/serve.py` 的 - **提权**:UAC 自提权重启会带上原始参数;`DNF90_GMWEB_CHILD=1` 的子进程不再提权 - **WebView2 数据目录**:固定在 `%LOCALAPPDATA%\DNF90Launcher\WebView2`,避免 exe 在只读目录/网络盘时窗口空白 - 排障与现场取证见 [`docs/启动器窗口风暴排查.md`](../docs/启动器窗口风暴排查.md) ## 打包 ```bash cd launcher python -m pip install pywebview pythonnet clr-loader pyinstaller python -m PyInstaller --clean --noconfirm "DNF90启动器.spec" # 产物:dist/DNF90启动器.exe ``` > 详见 [`docs/开发文档.md`](../docs/开发文档.md) 完整说明(环境搭建、架构、API 契约、常见问题)。