Files
youle_app_ohos/CLAUDE.md
T

10 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

项目概述

HarmonyOS NEXTAPI 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.json5build/ 产物、.hvigor/——它们由工具生成。
  • 调试产物统一放 docs/spike/:调试/排查时产生的临时文件(hilog 日志、hdc 截图、抓包、临时验证脚本等)一律落在 docs/spike/ 下,不要散在仓库根目录;这类文件不提交(应被 .gitignore 忽略),排查结束后可随时清理。临时埋点代码(验证用的 onTouch 打点、spike 方法等)验证完必须从源码移除。

常用命令

构建/运行/测试统一通过 devecocli(见 deveco-cli skill):

  • 构建 HAPdebug):devecocli build(底层 hvigor assembleHap,产物 entry/build/default/...
  • 运行到设备/模拟器:devecocli run;设备列表 devecocli devices
  • 真机/模拟器日志:devecocli loghilog
  • 查 SDK API 签名 / 鸿蒙文档:devecocli docs <关键词>(编码前核对 @ohos.* / @kit.* 实际签名)

测试(Hypium@ohos/hypium + @ohos/hamock):

  • 本地单元测试:entry/src/test/LocalUnit.test.etsList.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>,再次经 onLoadIntercepthandleReturnData 路由到预登记的 _fetchQueue 回调。务必忠实复刻此机制。
  • 原生→H5controller.runJavaScript("WebViewJavascriptBridge._handleMessageFromNative('"+json+"');");桥 JS 在 onPageEnd 注入(直接复用库原文件)。
  • 必须设 DefaultHandler(空实现):未注册的 handler 名落到默认空实现而不抛错,是"H5 调用永不报错"的最后防线。

双容器模型

  • BridgeGameContainer(大厅/子游戏,对应 Android webviewActivity):挂桥协议;app_data.js 必须在加载页面之前AppDataInjector 写入(H5 同步 <script src> 读取),切勿放到 onPageEndsetPostUrl/appservice 在首次进度 100% 时下发。子游戏切换 = 同容器 loadUrl,不重建组件。
  • GenericWebContainer(通用网页,对应 openwebActivity1):不挂桥,用 javaScriptProxy 注入 settings 对象(6 方法)+ runJavaScript 直调;回传走结果码 101 语义经 emitter/路由投回上层 Bridge 容器。

本期范围与占位桩

本期实现分享/登录/定位/音频/摇一摇/扫码/相机/震动/剪贴板/网络/设备等 Provider。视频房(声网)与支付用占位桩RoomStubProvider/PayStubProvider,§6.5):仍注册 handler,但 void 型空实现、有同步返回的回安全默认值、绝不触发出站推送——保证 H5 调用不报错、不卡死。闲聊不涉及(无 H5 桥接口)。组装根 buildCapabilities() 是唯一知道"全部能力"的地方,未来换回真实 Provider 即可。

两个最高风险"阻塞性验证"(必须最先证伪)

  • M1yy:// 的 iframe 导航是否稳定触发 onLoadIntercept(不同 ArkWeb 版本有差异)。失败回退:onInterceptRequest+WebSchemeHandler → 或改注入 javaScriptProxy 同步通道(对 H5 仍透明)。
  • M2file:// 加载下 H5 的 XHR/fetch 取本地资源是否可用。失败启用官方跨域方案(自定义协议 / onInterceptRequest)。

生产加固红线(附录 B

  • setWebDebuggingAccess(true) 仅 debug 包BuildProfile.DEBUG 守卫),release 必关。
  • 密钥(微信 AppSecret、支付 API_KEY不入客户端:登录走 code、支付签名走服务端。
  • 明文 HTTP 域名需在 module.json5 网络安全配置显式放行;gamepaywelcome 等外部唤起 scheme 在 abilities.skills.uris 声明。