长文档建议按当前分组逐页阅读;右侧辅助栏会保留当前位置和快速操作。
模块系统
模块系统把应用内“更多”页面、网站模块构建产物、Tauri 本地 bundle 桥接、Capacitor 本地缓存和远程 open_url 兜底连接起来。它不是简单 iframe 列表,而是一条从模块中心到运行时宿主的完整发布与加载链路。
模块中心
`src/utils/module_center.js` 提供 DEFAULT_MODULE_CENTER、normalizeModuleCenterEntry 和 buildModuleCenterCards。内置模块优先保证入口稳定,远程 catalog 再补充 manifest_url、描述、排序和兼容信息。
- 远程模块默认渠道是 main,也支持 dev 和 latest。
- 配置 modules、远程 catalogModules 与内置 DEFAULT_MODULE_CENTER 会按 id 合并。
- 内置游戏入口不依赖线上 catalog,避免远程目录滞后导致入口消失。
远程目录
`src/utils/more_modules.js` 使用 MODULE_CDN_BASE 指向模块 CDN。运行时缓存包含 hbu_more_module_state_v1、hbu_more_module_catalog_cache_v1、hbu_more_module_manifest_cache_v1 和 hbu_more_module_remote_source_rotation_v1。
- catalog.json 是渠道入口;manifest.json 是单模块发布入口。
- 远程候选地址会在当前 CDN、GitHub raw 和代理之间选择,但 iframe 打开时会避开常见代理。
- 缓存只是可用性兜底,不能当作发布成功证明。
内置模块清单
合成湖工大
默认 order=1,远程模块,来自 DEFAULT_MODULE_CENTER 与网站模块产物。
跳出湖工大
跳一跳风格小游戏,走 manifest_url 下载或远程打开链路。
2048 湖工大版
内置入口不依赖线上 catalog,避免 catalog 滞后导致入口消失。
笨鸟先飞
飞行点击类小游戏,构建后进入 website/public/modules。
湖工大富翁
校园投骰经营小游戏,模块包同样发布到 main、dev、latest。
湖工矿工
抓取类小游戏,module.json 指向 source_dir=project。
湖工记忆牌
翻牌配对模块,入口为 index.html。
湖工五子棋
本地双人五子棋,是网站模块契约覆盖的新增游戏之一。
manifest 字段契约
运行时打开链路
- MoreView.vue 首先读取远程配置 module_center,再调用 buildModuleCenterCards 合并 DEFAULT_MODULE_CENTER、配置 modules 与 catalogModules。
- normalizeModuleCenterEntry 会把 id、name、kind、order、key_required、view、min_compatible_version 和 manifest_url 归一化。
- 用户点击远程模块后,MoreView.vue 拉取 manifest.json,检查版本兼容,再调用 prepareAndOpenModule。
- prepareAndOpenModule 在桌面端优先走 prepare_module_bundle;在 Capacitor 端走本地 Filesystem 下载解压;在 Web 端走 remote-site 远程预览。
- MoreModuleHostView.vue 接收会话后通过 normalizeModuleHostSessionPayload 和 resolveModuleHostPreviewSource 修正 preview_url、preview_mode、open_url 和本地缓存路径。
tauri-local
桌面端本地桥接模式,preview_url 指向 http://127.0.0.1:4399/module_bundle/content/...。
capacitor-local
移动端本地文件模式,Filesystem 写入 Directory.Data 后通过 toNativeFileSrc 转换本地 URL。
remote-site
远程站点模式,使用 open_url 或远程候选地址直接在宿主 iframe 中打开。
Tauri 本地 bundle 桥
- src-tauri/src/modules/module_bundle.rs 使用 MODULE_CACHE_ROOT=more_modules,把模块按 channel/module_id/version 缓存在 AppCache 下。
- ModuleBundlePrepareRequest 接收 channel、module_id、version、package_url、package_urls、package_sha256、entry_path 和 min_compatible_version。
- prepare_module_bundle 会优先检查本地 metadata 与 package_sha256,命中时直接返回 ModuleBundlePrepareResult。
- 未命中缓存时下载 bundle.zip,校验 sha256,解压 site 内容,写入 bundle.zip 和 metadata。
- build_preview_url 生成本地预览地址,open_module_bundle_window 可打开独立模块窗口。
- resolve_module_bundle_file 负责把本地桥接 URL 映射回缓存目录文件,并阻断越界路径;文档中把这类风险称为 zip slip 防护。
构建与发布链
- scripts/build_website_modules.mjs 从 website/modules-src 扫描每个 module.json,跳过 disabled=true 的模块。
- module.json 至少要声明 id、name、entry_path,可选 source_dir、dist_dir、order、icon、key_required、min_compatible_version 和 release_notes。
- 脚本会在模块 source_dir 内执行 npm ci 或 npm install,再执行 npm run build,读取 dist_dir 作为静态站点产物。
- PUBLISH_CHANNELS 固定为 main、dev、latest;每个渠道都会写入 website/public/modules/{channel}/{moduleId}。
- 每个模块版本目录包含 site、bundle.zip、manifest.json;模块根目录也会写一份最新 manifest.json。
- 发布 manifest 会记录 published_channel 和 source_channel,catalog.json 按 order 排序,供客户端模块中心拉取。
模块安全边界
- 模块包可以渲染独立 HTML/JS,因此入口和远程来源必须来自受控 catalog 与 manifest。
- package_sha256 是完整性检查,不等同于发布者身份认证;安全隐私页已说明它不是非对称签名。
- entry_path 和 zip entry 都必须禁止绝对路径、`.`、`..`,防止 zip slip 或目录越界。
- MoreModuleHostView.vue 只能消费归一化后的 preview_url,不能直接信任远程 payload。
模块维护清单
- 新增模块时先补 website/modules-src/{id}/module.json,再确认源码目录、构建脚本、dist_dir 和 entry_path 都存在。
- 发布前运行 scripts/build_website_modules.mjs 需要注意它是写入型脚本,会安装依赖、构建模块并覆盖 website/public/modules。
- 模块入口异常时先检查 catalog.json、manifest.json、package_url、package_sha256、bundle.zip 和 preview_url。
- 桌面本地桥异常时检查 canUseLocalModuleBridgePreview、prepare_module_bundle 返回值、bundle_path 和 /module_bundle/content 路由。
- 移动端本地包异常时检查 Capacitor、Filesystem、toNativeFileSrc、local_preview_url 与 preview_mode=capacitor-local。
- 调试桥可通过 debug_reset_more_modules 清理模块缓存,但只能在明确开启调试桥和本地 token 正确时使用。
验证入口
scripts/test_more_module_bridge.mjs
该脚本读取远程 catalog.json、manifest.json,调用 /module_bundle/prepare,确认返回的 preview_url 命中 /module_bundle/content,并抽取 HTML 与资源文本确认不是占位页。
website_game_modules_contract.spec.ts
该契约测试确认 website/modules-src 中的游戏与 DEFAULT_MODULE_CENTER 对齐,覆盖 hbut_gomoku、 hbut_2048 等模块入口,并检查宿主不会在移动端使用桌面本地桥 URL。
源码证据索引
- 入口合并:src/utils/module_center.js 的 DEFAULT_MODULE_CENTER、normalizeModuleCenterEntry、buildModuleCenterCards。
- 远程目录与缓存:src/utils/more_modules.js 的 MODULE_CDN_BASE、hbu_more_module_state_v1、hbu_more_module_catalog_cache_v1、hbu_more_module_manifest_cache_v1、hbu_more_module_remote_source_rotation_v1。
- 用户入口:src/components/MoreView.vue 的 catalog 拉取、manifest 检查、isManifestVersionCompatible、prepareAndOpenModule 和导航 payload。
- 宿主入口:src/components/MoreModuleHostView.vue 与 src/App.vue 的 more_module_host、moduleHostSession、preview_url 修复逻辑。
- 桌面本地包:src-tauri/src/modules/module_bundle.rs 的 ModuleBundlePrepareRequest、ModuleBundlePrepareResult、prepare_module_bundle、open_module_bundle_window、resolve_module_bundle_file。
- HTTP 桥:src-tauri/src/http_server.rs 的 /module_bundle/prepare、/module_bundle/open、/module_bundle/content、/debug/reset_more_modules。
- 构建脚本:scripts/build_website_modules.mjs 与 website/modules-src/*/module.json。
- 专项验证:scripts/test_more_module_bridge.mjs 与 src/utils/website_game_modules_contract.spec.ts。
继续阅读
相关文档
当前页面读完后,可以按下面的交叉链接继续。用户文档、开发者文档、故障排查、参考资料和历史文档会互相补充。