- CLAUDE.md 工作约定新增「及时更新计划进度」:按 Plan 实施时主动更新 01_任务分解WBS 任务状态,与代码提交同节奏 - 01_任务分解WBS 新增「进度总览」:M0 全部 7 任务标记完成 ☑,M1~M6 未开始; 记录 M0 期间确立的项目决策(包名/横屏/验证策略/devecocli 无 test) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.6 KiB
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-cliskill /devecocli,不要手搓hvigorw命令或直连 MCP HTTP 桥。 - 禁止直接编辑
project.godot类生成文件;本项目对应的是 不要手改oh-package-lock.json5、build/产物、.hvigor/——它们由工具生成。
常用命令
构建/运行/测试统一通过 devecocli(见 deveco-cli skill):
- 构建 HAP(debug):
devecocli build(底层 hvigorassembleHap,产物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(任务 IDT-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(横切)。
三条不可违背的关键约束
- 桥核心对能力零感知:
feature_bridge不 import 任何具体能力,只持HandlerRegistry;能力启动时把自己的 handler 注册进去。新增能力 = 新增一个CapabilityProvider,零侵入桥核心。contractsHAR 用enum/interface固化所有 handler 名与 DTO,是全工程唯一来源(杜绝finsh/getcameraaAddress等拼写漂移)。 - 出站下发必须在 UI 线程(§5.5):
runJavaScript只能在 UI 线程调用,而能力回调常在非 UI 线程。BridgeController.dispatch内置 UI 线程守卫;Provider 不关心线程,任意线程callHandler最终都在 UI 线程下发。 - 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声明。