96 lines
10 KiB
Markdown
96 lines
10 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## 项目概述
|
||
|
||
HarmonyOS NEXT(API 12+,目标 SDK `6.1.1(24)`,runtimeOS `HarmonyOS`)上的 **TSGame 游戏大厅原生外壳**。目标:用 ArkTS / ArkUI 声明式 / Stage 模型重写原 Android WebView 外壳,使现有 H5(大厅 + 全部子游戏 + 活动/收银台等网页)**一行不改**即可运行。
|
||
|
||
当前处于 **M0 脚手架阶段**:`entry/` 仍是 DevEco 默认模板(`Index.ets` 为 Hello World),尚未落地设计文档中的多模块架构。实现工作以 `docs/设计文档/` 为唯一依据推进。
|
||
|
||
**原 Android 项目位于 `../tsgame_android`**(相对本仓库根目录)——即本项目要复刻的 WebView 外壳源头。遇到契约/行为存疑时,以该 Android 工程的实际实现为准对照。
|
||
|
||
## 工作约定
|
||
|
||
- **🔴 H5 零改动是最高铁律**:H5 网页(大厅 + 全部子游戏)必须**完美适配新项目,不做任何修改**。所有适配工作只能发生在原生侧——H5 向原生注册的接口、原生向 H5 注册的接口、双向接口的调用时机/参数/数据结构,全部以《契约规范》为准、与原 Android 行为完全一致。**任何"改一下 H5 就好了"的方案都不被接受**;H5 行为存疑时改原生实现去迁就 H5,而非反过来。这是判断一切技术方案是否成立的首要判据。
|
||
- **原生内部实现自由**:在不违背上述铁律的前提下,原生侧的内部实现(分层、模块拆分、数据结构、设计模式、用何种 HarmonyOS API/SDK、性能优化手段等)可以**根据实际情况自由设计**,不必拘泥于原 Android 的内部写法或设计文档的伪代码细节。铁律只约束"对 H5 暴露的边界行为",边界以内怎么实现由开发者按 HarmonyOS 最佳实践决定。
|
||
- **及时自动提交 git**:每完成一个可独立验收的小步骤(一个 Provider、一个状态机节点、一处可编译通过的改动)后,**主动执行 git 提交**,无需等待用户要求。提交信息用中文、说明"做了什么 + 对应契约/设计条目(如 §8、T-M1-04)"。⚠️ 仓库当前尚未 `git init`,首次提交前需先初始化。
|
||
- **及时更新计划进度**:按 `docs/设计文档/Plan/` 的计划实施时,每完成一个任务(`T-M{里程碑}-{序号}`)或推进一个里程碑,**主动更新对应计划文档的进度**——在 `01_任务分解WBS.md` 标记任务状态(`☐ 未开始 / ◐ 进行中 / ☑ 完成 / ⚠ 受阻`),受阻项同步登记到 `03_风险登记册.md`(见 `00_总体规划.md` §8 进度跟踪机制)。与代码提交同节奏,无需等用户提醒。
|
||
- HarmonyOS 相关操作(构建、运行、调试、设备、日志、查文档/SDK 签名)**必须**走 `deveco-cli` skill / `devecocli`,不要手搓 `hvigorw` 命令或直连 MCP HTTP 桥。
|
||
- **禁止直接编辑 `project.godot` 类生成文件**;本项目对应的是 **不要手改 `oh-package-lock.json5`、`build/` 产物、`.hvigor/`**——它们由工具生成。
|
||
- **调试产物统一放 `docs/spike/`**:调试/排查时产生的临时文件(hilog 日志、`hdc` 截图、抓包、临时验证脚本等)一律落在 `docs/spike/` 下,**不要散在仓库根目录**;这类文件不提交(应被 `.gitignore` 忽略),排查结束后可随时清理。临时埋点代码(验证用的 `onTouch` 打点、spike 方法等)验证完必须从源码移除。
|
||
|
||
## 常用命令
|
||
|
||
构建/运行/测试统一通过 `devecocli`(见 `deveco-cli` skill):
|
||
|
||
- 构建 HAP(debug):`devecocli build`(底层 hvigor `assembleHap`,产物 `entry/build/default/...`)
|
||
- 运行到设备/模拟器:`devecocli run`;设备列表 `devecocli devices`
|
||
- 真机/模拟器日志:`devecocli log`(hilog)
|
||
- 查 SDK API 签名 / 鸿蒙文档:`devecocli docs <关键词>`(编码前核对 `@ohos.*` / `@kit.*` 实际签名)
|
||
|
||
测试(Hypium,`@ohos/hypium` + `@ohos/hamock`):
|
||
|
||
- 本地单元测试:`entry/src/test/`(`LocalUnit.test.ets`、`List.test.ets`)——纯逻辑,不依赖设备
|
||
- 设备插桩测试:`entry/src/ohosTest/`(`Ability.test.ets` 等)——需真机/模拟器
|
||
- 通过 `devecocli test` 触发;目标:桥引擎 / `VersionResolver` / `MessageCodec` 单测覆盖率 **≥80%**
|
||
|
||
代码检查(`code-linter.json5`,仅作用于 `**/*.ets`):
|
||
|
||
- 规则集 `@performance/recommended` + `@typescript-eslint/recommended`
|
||
- **`@security/no-unsafe-*` 一组加密规则为 `error`**:禁用不安全的 AES/Hash/MAC/DH/DSA/ECDSA/RSA/3DES,写加密代码时务必遵守
|
||
|
||
## 架构(big picture,需读多文件才能掌握)
|
||
|
||
> 真正的架构在设计文档里,代码尚未落地。三份 SSOT 文档(修改实现前必读对应章节):
|
||
> - `docs/设计文档/TSGame_原生与H5接口契约总规范.md` —— **对外不可变契约**(H5 零改动的判据:handler 名、参数、数据结构、调用时机)
|
||
> - `docs/设计文档/TSGame_HarmonyOS框架设计与开发指南.md` —— HarmonyOS 侧如何实现(分层、桥、容器、启动)
|
||
> - `docs/设计文档/Plan/` —— 落地计划:`00_总体规划` / `01_任务分解WBS`(任务 ID `T-M{里程碑}-{序号}`)/ `02_测试与验收` / `03_风险登记册`
|
||
|
||
### 分层(依赖单向向下,跨层只依赖接口)
|
||
|
||
```
|
||
① 应用/编排层 EntryAbility · StartupOrchestrator · 路由 · DI 组装根(AppModule)
|
||
② 容器层 BridgeGameContainer(大厅/子游戏) │ GenericWebContainer(通用网页)
|
||
③ 桥引擎层 BridgeController · MessageCodec · HandlerRegistry · SettingsProxy
|
||
④ 能力层 每个原生能力 = 一个 CapabilityProvider 插件(share/login/location/...)
|
||
⑤ 领域服务层 ConfigManager · ResourceManager · AppDataInjector · VersionResolver
|
||
⑥ 平台服务层 HttpClient · Downloader · Unzipper · KvStore · LocalUploadServer · TaskScheduler
|
||
横切层 Logger/Tracer · ErrorCenter · EventBus · DIContainer · Contracts(TS类型 SSOT)
|
||
```
|
||
|
||
目标多模块拆分(HAR/HSP):`entry`(①②) / `feature_bridge`(③) / `feature_capabilities`(④) / `domain_resource`(⑤) / `platform`(⑥) / `contracts`(契约类型) / `common`(横切)。
|
||
|
||
### 三条不可违背的关键约束
|
||
|
||
1. **桥核心对能力零感知**:`feature_bridge` 不 import 任何具体能力,只持 `HandlerRegistry`;能力启动时把自己的 handler 注册进去。新增能力 = 新增一个 `CapabilityProvider`,零侵入桥核心。`contracts` HAR 用 `enum`/`interface` 固化所有 handler 名与 DTO,是全工程唯一来源(杜绝 `finsh`/`getcameraaAddress` 等拼写漂移)。
|
||
2. **出站下发必须在 UI 线程**(§5.5):`runJavaScript` 只能在 UI 线程调用,而能力回调常在非 UI 线程。`BridgeController.dispatch` 内置 UI 线程守卫;Provider 不关心线程,任意线程 `callHandler` 最终都在 UI 线程下发。
|
||
3. **TaskPool 只搬 Sendable**(§9.1):`@Concurrent` 任务跨线程传参/返回值必须是 Sendable,**不能传** callback / `WebviewController` / `UIAbilityContext`。下载/解压进度一律经 `emitter`/`AppStorage` 回 UI 线程,不要跨线程传函数。
|
||
|
||
### 桥协议核心("H5 零改动"命门,100% 复刻 lzyzsd/JsBridge)
|
||
|
||
- H5→原生:`Web().onLoadIntercept` 拦截 `yy://`(含 iframe 导航);`yy://return/` 前缀走回执,其余触发 `flushMessageQueue()`。
|
||
- **队列回传不靠 `runJavaScript` 返回值**:`_fetchQueue()` 在 H5 内把 `iframe.src` 置为 `yy://return/_fetchQueue/<队列JSON>`,再次经 `onLoadIntercept` → `handleReturnData` 路由到预登记的 `_fetchQueue` 回调。务必忠实复刻此机制。
|
||
- 原生→H5:`controller.runJavaScript("WebViewJavascriptBridge._handleMessageFromNative('"+json+"');")`;桥 JS 在 `onPageEnd` 注入(直接复用库原文件)。
|
||
- **必须设 `DefaultHandler`(空实现)**:未注册的 handler 名落到默认空实现而不抛错,是"H5 调用永不报错"的最后防线。
|
||
|
||
### 双容器模型
|
||
|
||
- **BridgeGameContainer**(大厅/子游戏,对应 Android `webviewActivity`):挂桥协议;`app_data.js` 必须在**加载页面之前**由 `AppDataInjector` 写入(H5 同步 `<script src>` 读取),切勿放到 `onPageEnd`;`setPostUrl`/`appservice` 在首次进度 100% 时下发。子游戏切换 = 同容器 `loadUrl`,不重建组件。
|
||
- **GenericWebContainer**(通用网页,对应 `openwebActivity1`):**不挂桥**,用 `javaScriptProxy` 注入 `settings` 对象(6 方法)+ `runJavaScript` 直调;回传走结果码 101 语义经 `emitter`/路由投回上层 Bridge 容器。
|
||
|
||
### 本期范围与占位桩
|
||
|
||
本期实现分享/登录/定位/音频/摇一摇/扫码/相机/震动/剪贴板/网络/设备等 Provider。**视频房(声网)与支付用占位桩**(`RoomStubProvider`/`PayStubProvider`,§6.5):仍注册 handler,但 void 型空实现、有同步返回的回安全默认值、绝不触发出站推送——保证 H5 调用不报错、不卡死。**闲聊不涉及**(无 H5 桥接口)。组装根 `buildCapabilities()` 是唯一知道"全部能力"的地方,未来换回真实 Provider 即可。
|
||
|
||
### 两个最高风险"阻塞性验证"(必须最先证伪)
|
||
|
||
- **M1**:`yy://` 的 iframe 导航是否稳定触发 `onLoadIntercept`(不同 ArkWeb 版本有差异)。失败回退:`onInterceptRequest`+`WebSchemeHandler` → 或改注入 `javaScriptProxy` 同步通道(对 H5 仍透明)。
|
||
- **M2**:`file://` 加载下 H5 的 XHR/fetch 取本地资源是否可用。失败启用官方跨域方案(自定义协议 / `onInterceptRequest`)。
|
||
|
||
### 生产加固红线(附录 B)
|
||
|
||
- `setWebDebuggingAccess(true)` **仅 debug 包**(`BuildProfile.DEBUG` 守卫),release 必关。
|
||
- 密钥(微信 `AppSecret`、支付 `API_KEY`)**不入客户端**:登录走 code、支付签名走服务端。
|
||
- 明文 HTTP 域名需在 `module.json5` 网络安全配置显式放行;`gamepaywelcome` 等外部唤起 scheme 在 `abilities.skills.uris` 声明。
|