From 46f65de7edc227fd5bfc51210caa62ceb0d7208c Mon Sep 17 00:00:00 2001 From: Joywayer Date: Tue, 7 Jul 2026 12:21:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E8=A7=84=E8=8C=83=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=B8=A4=E6=9D=A1=EF=BC=9A=E5=B8=B8=E9=87=8F=E5=8C=96?= =?UTF-8?q?=20id=EF=BC=88=E5=90=AB=E7=BE=A4=E7=BB=84/Spine=EF=BC=89+=20?= =?UTF-8?q?=E6=98=BE=E9=9A=90=E8=B5=B0=20showXxx/hideXxx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 强化「常量集中、禁硬编码」(05 §4 / README 红线速查 / 05 §11 审查表): 明确 UI 代码禁止任何硬编码 id/裸值,覆盖精灵/群组/图层/图片/声音/Spine 等全部 id 与资源,一律用对应常量;补 Spine→Spine 动作配置映射。 - 新增「显隐走 showXxx/hideXxx 接口」(02 §3 范式第4条 / 05 §9 红线 / README 红线速查 / 05 §11 审查表):UI 组件及零件的精灵/群组显隐必须由组件 暴露的 showXxx/hideXxx 控制,禁止别处直接用其精灵/群组 id 去 show/hide, 否则绕过组件、状态分散、重连刷新不一致(与 UI 组件专职一脉相承)。 - 显隐条同进 README 红线速查(@import 常驻层);未改任何小节标题, 链接/锚点审计通过。 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/client/development-guide/02-渲染与UI组件体系.md | 1 + docs/client/development-guide/05-开发规范与红线.md | 12 +++++++----- docs/client/development-guide/README.md | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/client/development-guide/02-渲染与UI组件体系.md b/docs/client/development-guide/02-渲染与UI组件体系.md index ac9cf5f..a69dfe6 100644 --- a/docs/client/development-guide/02-渲染与UI组件体系.md +++ b/docs/client/development-guide/02-渲染与UI组件体系.md @@ -128,6 +128,7 @@ MyView.init = function (config) { 1. **数据集中在 `this.data`**:组件及其下每个「零件 UI」的自有数据全部收拢到 `this.data.*`,**不散落**在实例其他字段或全局;界面能否重建只取决于 `this.data`。 2. **每个 UI 都有 `setXxx` / `refreshXxx` 成对方法**:`setXxx(...)` **只写数据**到 `this.data`、不碰精灵;`refreshXxx()` **只据 `this.data` 画界面**、不改数据。两者职责单一、互不越界。 3. **组件有一个总 `refresh()`**:顺序调用其下所有零件的 `refreshXxx()`,据 `this.data` 完整重画。**任何时候调 `refresh()` 都能无歧义重建正确界面**(断线重连、切 app 回来、网页刷新都复用它,不另写一套渲染)。 +4. **显隐走 `showXxx` / `hideXxx` 接口**:组件(及每个「零件 UI」)的精灵/群组显隐,由组件自身暴露的 `showXxx()`/`hideXxx()` 语义方法控制;外部**只调这些接口**,**禁止**在别处直接用该组件/零件的精灵 ID、群组 ID 去 `SpriteManager.show/hide`(或 `showGroup/hideGroup`)——那样绕过组件、状态分散,重连/刷新时不一致。 ```js GameView.setScore = function (v) { this.data.score = v; }; // 只写数据 diff --git a/docs/client/development-guide/05-开发规范与红线.md b/docs/client/development-guide/05-开发规范与红线.md index dfc9d2d..e2022ed 100644 --- a/docs/client/development-guide/05-开发规范与红线.md +++ b/docs/client/development-guide/05-开发规范与红线.md @@ -49,12 +49,13 @@ - **精灵只走 `SpriteManager`**:UI 代码禁止直接调 `GameABCUtils`/引擎原生 API。 - **ID 守范围**:精灵 1001–3000、群组 ≥201、普通图层 101–200、弹窗图层 301–400(另有 501–600、701+ 备用段);框架保留 1–1000 及 3001+(精灵)等交替段,不可占用;ID 必须与编辑器一致,不编造。 - **检查返回值**:`SpriteManager.*` 返回 `false` 即 ID/范围有误,及时暴露。 -- **常量集中、禁硬编码**:精灵 ID / 图片资源 ID / 坐标尺寸 / 动画时长帧数 / 音效 ID / 事件名,一律定义在对应常量文件,业务代码只引用: - - 精灵结构 → 精灵结构常量(主界面/弹窗分文件) +- **常量集中、禁硬编码**:UI 代码**禁止出现任何硬编码的 id 或裸值**——精灵 ID / 群组 ID / 图层 ID / 图片资源 ID / 声音 ID / Spine 资源 / 坐标尺寸 / 动画时长帧数 / 事件名,一律定义在对应常量文件,业务代码**只引用常量**: + - 精灵结构(含群组 / 图层 ID)→ 精灵结构常量(主界面/弹窗分文件) - 图片资源 → 图片资源常量 - 布局坐标 → 布局常量 - 动画参数 → 动画配置 - - 音效 ID → 音效资源常量 + - 音效 / 语音 ID → 音效资源常量 + - Spine 资源 → Spine 动作配置 - 事件名 → `EventBus.Events`(专属在子游戏事件常量文件) - 整合入口 → 精灵常量整合入口(**最后加载**) @@ -100,6 +101,7 @@ - 一个职能只在一个模块实现,其他模块**调用而非重造**:渲染找 `SpriteManager`、动画找 `AnimationManager`(及游戏动画封装)、音频找游戏音频管理、Spine 找 `SpineMgr`(及 Spine 回调分发)、发包找语义化发包封装、收包分发找收包分发器。 - **UI 组件专职自己的界面**:每个界面的数据与渲染**只由其对应 UI 组件实现**,组件对外提供 `setXxx`/`refreshXxx` 与语义化公开方法。别的模块(controllers/managers/其他组件)要改动或刷新某界面,一律**调用该组件的公开接口**,**禁止**在别处重复实现重叠或类似的界面数据/渲染逻辑(否则同一界面出现多份状态源,重连/刷新时必然不一致)。 +- **显隐走 `showXxx`/`hideXxx` 接口**:UI 组件及其「零件 UI」的精灵/群组显隐,必须由组件自身暴露的 `showXxx()`/`hideXxx()` 语义接口控制;**禁止**在别处直接用该组件/零件的精灵 ID、群组 ID 去 `SpriteManager.show/hide`(或 `showGroup/hideGroup`)控制其显隐——绕过组件即状态分散,重连/刷新时必然不一致。 - 写代码前先问“这段属于谁的职责”,属于别人就调用它,不在本模块复制一份近似实现。 --- @@ -120,14 +122,14 @@ | 语言 | 严格 ES5;新文件插对加载顺序 | | 框架中立 | 框架无玩法逻辑/专属常量;专属内容归子游戏 | | 渲染 | 只走 `SpriteManager`;ID 守范围、不编造;查返回值 | -| 常量 | 精灵/资源/坐标/动画/音效/事件全集中,禁硬编码裸值 | +| 常量 | 精灵/群组/图层/图片/声音/Spine/坐标/动画/事件全进常量;UI 代码禁硬编码 id 与裸值 | | 组件 | 继承 `BaseComponent`;事件 `addEventListener`;`destroy` 清动态精灵/定时器 | | 数据 | 服务端权威(核心运算/裁定在服务端);组件自有数据集中 `this.data`;每个 UI/零件有 set/refresh 对、组件有总 `refresh` | | 节奏 | 先写数据后表现;动画回调只刷界面、**不写核心数据**;重画可随时据数据还原界面 | | 成败 | 只认 `data.success`,禁 `status` 兜底 | | 收发包 | 发走语义化发包封装、收走收包分发器;业务不进 `Game_Modify` | | 职责 | 一职能一模块,调用不重造 | -| UI 职责 | 每个界面的数据与渲染只在其 UI 组件实现;别处调组件接口,不重叠/重造 | +| UI 职责 | 每个界面的数据/渲染/显隐只在其 UI 组件实现;别处调组件接口(含 `showXxx`/`hideXxx`),不重叠重造、不直接用其精灵/群组 id 控显隐 | | 重连 | 断线重连 + 硬刷新都要处理;本质=恢复数据→各组件 set-refresh;复用同一重画路径 | --- diff --git a/docs/client/development-guide/README.md b/docs/client/development-guide/README.md index c84aaf8..169e987 100644 --- a/docs/client/development-guide/README.md +++ b/docs/client/development-guide/README.md @@ -60,11 +60,12 @@ BaseComponent / UIManager(ui,组件化与场景) ← gameabc-framework( - **严格 ES5**:用 `var`/`function`/`Object.create`,禁 `let`/`const`/箭头/模板串/`class`。 - **框架游戏中立**:`gameabc-framework/` 内**不得**出现任何具体玩法逻辑或专属常量;玩法专属的事件/资源/配置一律定义在子游戏侧(如玩法事件在子游戏的事件常量文件里追加到 `EventBus.Events`)。 - **精灵只走 SpriteManager**:UI 代码**禁止**直接调 `GameABCUtils` 或引擎原生 API;ID 必须落在规定范围(精灵 1001–3000、群组 ≥201、图层 101–200/弹窗 301–400,另有 501–600、701+ 备用段,框架保留 1–1000 及 3001+ 等交替段)。 -- **常量集中、禁硬编码**:精灵 ID/图片资源 ID/坐标尺寸/动画时长/音效 ID 一律定义在对应常量文件,业务代码引用,**不内联裸值**。 +- **常量集中、禁硬编码**:UI 代码**禁止任何硬编码 id / 裸值**——精灵 ID / 群组 ID / 图层 ID / 图片资源 ID / 声音 ID / Spine 资源 / 坐标尺寸 / 动画时长 / 事件名 一律定义在对应常量文件、只引用常量。 - **服务端权威、前端只展示**:核心运算与胜负裁定以服务端为准、数据以服务端为权威;前端只做界面展示与玩家交互,本地数据仅为渲染副本,不做权威计算。 - **组件走 BaseComponent**:UI 组件继承 `BaseComponent`,事件用 `this.addEventListener` 注册(`destroy()` 自动清理,防泄漏);动态精灵/定时器在 `onDestroy` 清理。 - **组件数据自持 + set-refresh**:组件自有数据集中 `this.data`;每个 UI/零件有 `setXxx`(只写数据)/`refreshXxx`(只据数据画)对,组件有总 `refresh()` 可据数据重建界面。 - **UI 组件专职自己的界面**:每个界面的数据与渲染只由其对应 UI 组件实现;别的模块要改/刷该界面一律**调该组件的公开接口**(`setXxx`/`refreshXxx`/语义方法),**禁止**在别处重复实现重叠或类似的界面数据/渲染逻辑。 +- **显隐走 `showXxx`/`hideXxx`**:UI 组件/零件的精灵、群组显隐必须由组件暴露的 `showXxx`/`hideXxx` 接口控制;**禁止**别处直接用其精灵 ID/群组 ID 去 `SpriteManager.show/hide` 控显隐。 - **数据优先、表现延后**:收到推送先 `setXxx` 写数据、再播动画;动画的开始/结束/出错回调里**只刷界面、不写核心数据**。即使动画缺失/卡住/出错,数据、逻辑、界面仍正确、互不影响。 - **重连即重画(断线重连 + 硬刷新都要处理)**:重连/页面重载的本质是**恢复数据 → 调各 UI 组件 set-refresh 恢复数据与界面状态**,复用同一条重画路径,不为重连单写一套渲染(详见 04 §3.3、05 §6)。 - **成败只认 `data.success`**:前端一律 `if (!data.success)` 判成败,**不**用 `status`/`code`,**不**写 `status` 兼容兜底。