diff --git a/Assets/Plugins/UIModule.meta b/Assets/Plugins/UIModule.meta deleted file mode 100644 index 0e056a0..0000000 --- a/Assets/Plugins/UIModule.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a14acd1a7cab53742bedb7cb53817cba -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Plugins/UIModule/docs.meta b/Assets/Plugins/UIModule/docs.meta deleted file mode 100644 index 593a49f..0000000 --- a/Assets/Plugins/UIModule/docs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c7bac844b7e89c04c940ad4c471ab8f8 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Plugins/UIModule/docs/UI-5层架构设计规范.md b/Assets/Plugins/UIModule/docs/UI-5层架构设计规范.md deleted file mode 100644 index 43b1454..0000000 --- a/Assets/Plugins/UIModule/docs/UI-5层架构设计规范.md +++ /dev/null @@ -1,427 +0,0 @@ -# UI 五层架构设计规范(UseCase / RawData / Controller / Context / View) - -## 1. 文档目标 - -本文定义一套可长期复用的 UI 分层设计方案,用于约束 UI 模块的职责边界、依赖方向、通信方式和测试策略。 - -- 本文描述的是规范,不是对某个项目现状的总结 -- 项目内目录或基类只作为落地示例,不改变本文的抽象约束 -- 本文重点约束 UIForm 级模块;子组件(`Item`、`Area` 等)可只实现 `Context + View` -- Unity GameFramework 的底层细节不在本文展开,本文只约束项目内 UI 代码组织 - -补充说明(插件化落地): - -- 本规范通过 `Assets/Plugins/UIModule/` 以**可选插件**方式落地 -- 插件无独立程序集,通过 `.asmref` 融入原项目各程序集: - - `SepCore.Base.UIModule.asmref`:`Base/` → `SepCore.Base` - - `SepCore.Runtime.UIModule.asmref`:`Runtime/` → `SepCore.Runtime` - - `SepCore.Presentation.UIModule.asmref`:`UI/` → `SepCore.Presentation` -- `Runtime/` 内 `SepCore.UI` 命名空间放置基础抽象、UseCase、RawData;`SepCore.CustomComponent` 放置 `UIRouterComponent` -- `UI/` 内 `SepCore.UIModule` 命名空间放置 Controller / Context / View -- 不启用插件时,项目可继续使用原有基座 UI 路线 -- 启用插件时,必须通过 `UIRouterComponent` 统一管理 `Controller / UseCase` -- 通过 `UIRouterComponent` 打开的 UIForm 必须配置对应 Controller,缺少绑定视为接入错误,不回退到原始 UI 打开路径 -- 当前插件对外 UI 生命周期接口为 async-first:`OpenUIAsync / CloseUIAsync` - -## 2. 核心原则 - -### 2.1 单向数据职责 - -UI 的职责链路固定为: - -```text -外部流程 - -> Controller - -> UseCase - -> RawData / Result - -> BuildContext - -> View - -View - --(UI 专用事件)--> Controller -``` - -说明: - -- `UseCase` 只负责业务规则、状态推进和纯业务数据生成 -- `Controller` 是 UI 编排中心,也是唯一允许构建 `Context` 的层 -- `View` 只负责渲染和抛出交互,不直接处理业务状态 - -### 2.2 严格分离业务数据与展示数据 - -- `RawData` 默认是业务传输模型,不承载展示模型。 -- 轻量 UI 可携带回调委托,但回调只允许由 Controller 注册和触发,不得进入 Context / View。 -- `Context` 是纯展示数据,不进入 `UseCase` -- `UseCase` 不能返回 `Context` -- `View` 只能消费 `Context` - -### 2.3 Controller 是 UI 唯一外部入口 - -对于 UIForm 级模块,外部流程只能通过 `Controller` 驱动 UI: - -- 异步打开 UI -- 异步关闭 UI -- 绑定 `UseCase` -- 刷新 UI -- 响应 UI 专用事件 - -`View` 不作为外部流程的直接依赖对象。 - -## 3. 五层职责定义 - -### 3.1 UseCase 层 - -职责:封装 UI 对应的业务用例,负责业务规则、状态推进、校验和纯业务结果输出。 - -约束: - -- 实现 `IUIUseCase` -- 命名:`XXXFormUseCase` -- 对外提供语义化方法,例如 `CreateInitialModel`、`TryRefresh`、`Select`、`Confirm` -- 返回值只能是 `RawData` 或纯业务结果对象,例如 `XXXResult`、`XXXActionResult` -- 不依赖 `Context`、`View`、`UGuiForm`、`MonoBehaviour` 等 UI 类型 -- 不负责 UI 资源加载、文本拼装、颜色选择、图标转换等展示处理 -- 不发布 UI 专用事件 - -适用场景: - -- UI 会读写领域状态 -- UI 存在明确业务规则、条件分支、校验或状态推进 -- UI 的交互结果需要被测试和复用 - -### 3.2 RawData 层 - -职责:承载 `UseCase -> Controller` 的纯业务传输模型。 - -约束: - -- 命名:`XXXFormRawData` -- 只描述业务数据,不包含 UI 展示行为 -- 可以包含领域对象、配置对象、标识符、枚举、数值和纯数据集合 -- **轻量场景下可携带回调委托**,由 Controller 在构建 Context 前完成注册 -- 不允许依赖 `Context`、`View`、`Sprite`、`TMP_Text` 等展示相关类型 -- 不允许直接使用 `XXXItemContext`、`XXXFormContext` 作为字段类型 - -说明: - -- `RawData` 的目标是表达“业务上发生了什么” -- `Context` 的目标是表达“界面应该怎么显示” -- `RawData` 可以携带行为(如回调),`Context` 只承载展示数据,不允许携带回调 - -### 3.3 Controller 层 - -职责:UI 编排层,负责连接外部流程、`UseCase`、`View`,并统一管理 UI 生命周期与展示状态。 - -约束: - -- 对启用 `UIRouterComponent` 管理的 UIForm,必须存在可实例化的 Controller 绑定;未绑定时 Router 应直接失败并输出 Error,不允许 fallback 到 `GameEntry.UI.OpenUIForm(...)` -- 命名:`XXXFormController` -- 可基于 `UIFormControllerBase` 实现 -- 通过 `BindUseCase(IUIUseCase)` 注入用例并做类型校验 -- 当前对外入口为 `OpenUIAsync(object userData = null, float timeout = 30f)` 与 `CloseUIAsync(...)` -- `OpenUIAsync` 只允许外部传入 `RawData` 或可转换为 `RawData` 的参数,不接受外部传入 `Context` -- 当 `userData == null` 且 UI 绑定了 UseCase 时,Controller 应通过 UseCase 构造初始 RawData,再转换为 Context -- 当 `userData == null` 且 UI 没有 UseCase 时,Controller 可按 UI 类型决定构造默认 RawData / 默认 Context,或返回失败并输出 warning -- 负责 `RawData / Result -> Context` 的转换,常见形式为 `BuildContext` -- 负责事件订阅与解除订阅,且必须成对出现 -- 负责全量刷新与局部刷新策略 -- 在同类 UI 可能多实例时,负责通过 `sender`、`serialId` 或其他等价标识限制事件只作用于当前 UI 实例 -- **推荐子类显式组织业务时序**:参数校验、Context 构造、临时状态缓存、关闭后续动作等都直接写在具体 Controller 中;基类只提供共用开关窗机制,不隐藏子类业务时机 - -允许职责: - -- 将业务数据转换为展示友好的文本、图标、颜色、列表状态 -- 在必要时查询本地化、资源映射或展示适配逻辑 - -禁止职责: - -- 在 `Controller` 中堆叠大段领域业务规则 -- 绕过 `Context` 直接把业务对象塞给 `View` -- 直接修改其他 UI 的内部 `View` - -### 3.4 Context 层 - -职责:承载“可直接驱动 UI 展示”的上下文数据。 - -约束: - -- 继承 `UIContext` -- 命名:`XXXFormContext`、`XXXItemContext`、`XXXAreaContext` -- 只能由 `Controller` 构建和更新 -- 字段以展示友好为目标,例如标题、描述、图标、颜色、状态、列表、按钮文案 -- **不允许携带回调委托或行为**,交互行为由 Controller 注册,View 通过 UI 专用事件通知 Controller -- 允许组合子 `Context` -- 不进入 `UseCase` - -说明: - -- `Context` 可以包含展示层需要的最终数据 -- `Context` 可以是“已格式化”的显示数据 -- 但这些数据必须由 `Controller` 负责准备,而不是 `UseCase` - -### 3.5 View 层 - -职责:纯表现层,负责控件绑定、渲染刷新、动画触发和交互事件抛出。 - -约束: - -- Form 类继承 `UGuiForm`,子组件通常继承 `MonoBehaviour` -- 命名:`XXXForm`、`XXXItem`、`XXXArea` -- 提供打开、关闭、刷新入口: - - `UGuiForm`:`OnOpen(object userData)`、`OnClose(bool isShutdown, object userData)`、`RefreshUI(Context)` - - `MonoBehaviour` 子组件:可统一设计为 `OnOpen(Context)`、`OnClose()`、`RefreshUI(Context)` -- 只消费 `Context` -- 用户交互通过 UI 专用事件通知 `Controller` -- 不承载业务规则、流程推进、数据筛选和领域状态修改 -- 不订阅全局业务事件 - -允许职责: - -- 本地控件显隐 -- 动画播放 -- 一次性的纯视觉状态缓存 - -禁止职责: - -- 直接调用 `UseCase` -- 直接修改领域状态 -- 订阅或处理全局业务事件 -- 将自己作为业务逻辑的入口 - -## 4. UI 类型分级 - -### 4.1 标准五层 UI - -组成:`UseCase + RawData + Controller + Context + View` - -适用条件: - -- UI 需要读写领域状态 -- UI 存在明确业务规则或分支 -- UI 交互会改变游戏流程、角色状态、背包、战斗结果等业务对象 -- UI 行为需要被自动化测试覆盖 - -默认规则: - -- 新增业务型 UI,优先使用完整五层 - -### 4.2 轻量 UI - -组成:`Controller + Context + View` - -说明: - -- `UseCase` 对轻量 UI 不强制 -- `RawData` 也不是强制层,可按需要补充 -- 轻量 UI 仍然必须通过 `Controller` 驱动,不能让 `View` 直接承担外部入口 - -适用条件: - -- 只承担展示、导航、确认、提示等轻量职责 -- 没有独立的业务规则或状态推进 -- 只需要把已有参数转换成界面展示 - -升级规则: - -- 一旦轻量 UI 开始承载业务规则、校验或状态推进,应升级为标准五层 UI - -## 5. 依赖方向约束 - -允许依赖: - -- `UseCase -> 领域对象 / 纯业务服务 / RawData / Result` -- `Controller -> UseCase + RawData + Result + Context + View + UI 专用事件` -- `Context -> 子 Context / 纯展示值对象` -- `View -> Context + UI 专用事件` - -禁止依赖: - -- `UseCase -> Context / View / Unity 具体展示组件` -- `RawData / Result -> Context / View` -- `Context -> View / UseCase` -- `View -> UseCase` -- `View -> 全局业务事件` -- `View -> 领域状态修改` - -### 5.1 插件化分层建议 - -建议分层如下: - -- `SepCore.Base`:UI 专用事件(`SepCore.Event`) -- `SepCore.Runtime`:基座与业务流程层,同时融入插件 `Runtime/` 中的基础抽象、UseCase、RawData 与 `UIRouterComponent` -- `SepCore.Presentation`:Controller、Context、View(`SepCore.UIModule`) -- Editor:`UIModule.Editor`,代码命名空间当前为 `SepCore.UIModule.Editor` - -插件目录与程序集映射: - -- `Base/` → `SepCore.Base` -- `Runtime/` → `SepCore.Runtime` -- `UI/` → `SepCore.Presentation` - -建议依赖方向: - -```text -SepCore.Base(UI 专用事件) - ↑ -SepCore.Runtime(基础抽象 + UseCase + RawData + Router) - ↑ -SepCore.Presentation(Controller + Context + View) -``` - -约束: - -- `SepCore.Base` / `SepCore.Runtime` 不反向依赖 Presentation 层 -- UI 专用事件虽在 `SepCore.Event` 命名空间,但语义上仍归属对应 UI 模块,禁止被业务模块复用 -- 业务流程层通过插件入口(如 Router)调用五层 UI 能力 -- 插件内无独立程序集,通过 `.asmref` 文件融入原项目编译 - -## 6. 事件通信规范 - -### 6.1 UI 与 Controller 的通信方式 - -`View` 与 `Controller` 的通信通过当前 UI 模块专用事件完成。 - -约束: - -- UI 专用事件只服务于当前 UI 模块 -- 这些事件不是业务公共事件 -- 业务模块、流程模块、领域模块不应复用这些事件 -- UI 专用事件可统一放在 `SepCore.Event` 命名空间下,但事件语义仍归属对应 UI 模块,禁止被业务模块复用 -- 如果底层使用全局事件总线实现,也只能把它当作“传输通道”,不能把事件语义扩散成全局契约 - -### 6.2 事件边界 - -- `View -> Controller`:使用 UI 专用事件 -- `Controller -> View`:通过刷新 `Context` 或调用 `View` 的渲染接口 -- `Controller -> UseCase`:直接方法调用 -- `UseCase -> Controller`:通过返回 `RawData / Result`,不通过 UI 事件反推界面 -- `外部流程 -> Controller`:只传入 `RawData` 或可转换为 `RawData` 的参数,不传入 `Context` - -### 6.3 事件安全要求 - -- 同类 UI 可同时存在时,事件必须只作用于当前窗体实例;可通过 `sender`、`serialId` 或其他等价标识实现 -- UI 专用事件命名应体现模块归属,避免语义过宽 -- 同一 UI 可以按需要使用“多个精细事件”或“单一事件 + 子类型/按钮编号”的方式建模;例如当前 Dialog 使用 `DialogEventArgs + ButtonId` - -## 7. 标准交互流程 - -### 7.1 有 UseCase 的标准流程 - -```text -Procedure / GameState - -> BindUseCase - -> await OpenUIAsync(rawData or null) - -Controller - -> 如果外部传入 RawData:直接使用该 RawData - -> 如果外部未传入 RawData:UseCase.BuildRawData() / CreateInitialModel() - -> BuildContext(rawData) - -> View.RefreshUI(context) - -View - --(UI 专用事件)--> Controller - -Controller - -> UseCase.Action(...) - -> Result / RawData - -> BuildContext / PartialRefresh - -> View.RefreshUI(...) -``` - -说明: - -- 外部流程不传入 `Context` -- `Context` 只在 Presentation 层内由 Controller 构建 -- `OpenUIAsync(null)` 对有 UseCase 的 UI 是合法入口,表示由 UseCase 构造初始 RawData - -### 7.2 无 UseCase 的轻量流程 - -```text -外部流程 - -> await OpenUIAsync(rawData) - -Controller - -> BuildContext(rawData) - -> View.RefreshUI(context) - -View - --(UI 专用事件)--> Controller - -Controller - -> 处理轻量逻辑或路由动作 - -> 更新 Context / 打开其他 UI / 关闭当前 UI -``` - -说明: - -- 轻量 UI 如果没有默认数据来源,`OpenUIAsync(null)` 可以失败并输出 warning -- Dialog 这类提示型 UI 属于必须由外部传入 RawData 的轻量 UI -- 即使是轻量 UI,外部也不传入 `Context`,Context 仍由 Controller 构建 - -### 7.3 关闭流程 - -1. 外部流程或 `Controller` 调用 `CloseUIAsync(...)` -2. `Controller` 解除事件订阅 -3. `Controller` 清理本次交互缓存,例如回调、临时 `UserData` 和局部状态 -4. `View.OnClose` 清理本地视觉状态 -5. 下次打开时重新按 `Context` 初始化 - -## 8. 目录与命名规范 - -目录示例以插件目录为例(`Assets/Plugins/UIModule`)。 - -- 插件 `Base/Event//`:UI 专用事件(命名空间 `SepCore.Event`) -- 插件 `Runtime/Base/`:五层 UI 基础抽象(命名空间 `SepCore.UI`) -- 插件 `Runtime//`:UseCase、RawData(命名空间 `SepCore.UI`) -- 插件 `Runtime/` 根目录:`UIRouterComponent`(命名空间 `SepCore.CustomComponent`) -- 插件 `UI//`:Controller、Context、View(命名空间 `SepCore.UIModule`) -- 五层同名前缀保持一致,例如 `ShopForm*`、`LevelUpForm*` -- 子组件上下文命名:`RoleItemContext`、`RewardItemContext`、`DisplayAreaContext` -- 结果对象命名:`XXXResult`、`XXXActionResult` -- 轻量 UI 可以省略 `UseCase` 和 `RawData`,但不省略 `Controller`、`Context`、`View` - -## 9. 测试规范 - -### 9.1 自动化测试范围 - -如果一个 UI 具备 `UseCase`,并且需要补自动化测试,则统一使用 EditMode 测试。 - -优先覆盖: - -- 初始化模型生成 -- 业务分支与校验 -- 用户动作对应的结果对象 -- 边界条件和非法输入 - -### 9.2 Controller / View 的验证策略 - -`Controller` 和 `View` 以人工验收为主,重点验证: - -- 首次打开 -- 交互刷新 -- 局部刷新 -- 关闭重开 -- 非法参数或空数据输入时的表现 - -## 10. 落地检查清单 - -新增 UI 时,至少检查以下事项: - -1. 先判断该 UI 属于标准五层还是轻量 UI -2. 使用 `UIRouterComponent` 管理的 UIForm 必须配置可实例化的 Controller 绑定 -3. 如果存在业务规则或状态推进,必须引入 `UseCase` -4. 外部打开 UI 时只传入 `RawData` 或可转换为 `RawData` 的参数,不传入 `Context` -5. `OpenUIAsync(null)` 对有 UseCase 的 UI 应通过 UseCase 构造初始 RawData -6. `RawData` 中不得出现 `Context` 类型 -7. `Context` 只能在 `Controller` 中构建 -8. `View` 不得订阅全局业务事件 -9. `View` 的交互只能通过 UI 专用事件上报 -10. `Controller` 必须成对管理事件订阅与解除订阅 -11. `Controller` 必须在关闭时清理本次交互缓存 -12. 有 `UseCase` 且需要补自动化测试时,测试写入 EditMode - -## 11. 非目标说明 - -- 本文不讨论历史实现,也不为历史写法背书 -- 本文不要求所有 UI 必须强制引入 `UseCase` -- 本文不展开底层 UI 框架或事件系统实现细节 diff --git a/Assets/Plugins/UIModule/docs/UI-5层架构设计规范.md.meta b/Assets/Plugins/UIModule/docs/UI-5层架构设计规范.md.meta deleted file mode 100644 index be74e22..0000000 --- a/Assets/Plugins/UIModule/docs/UI-5层架构设计规范.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4995b75eba7756d40939282a00f7c04a -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Plugins/UIModule/docs/UIModule-使用说明.md b/Assets/Plugins/UIModule/docs/UIModule-使用说明.md deleted file mode 100644 index ced358a..0000000 --- a/Assets/Plugins/UIModule/docs/UIModule-使用说明.md +++ /dev/null @@ -1,220 +0,0 @@ -# UIModule 使用说明(可选插件) - -## 1. 定位 - -`UIModule` 是基于 UGF 的可选 UI 插件,通过 `.asmref` 融入现有项目程序集: - -- `Base/` → `SepCore.Base` -- `Runtime/` → `SepCore.Runtime` -- `UI/` → `SepCore.Presentation` - -插件本身没有独立运行时程序集;基础抽象、事件、Controller、View 会并入宿主程序集编译。 -不启用插件时,项目仍可继续使用原有 UI 路线。 - ---- - -## 2. 接入步骤 - -1. 确保以下 `.asmref` 已存在于插件目录: - - `SepCore.Base.UIModule.asmref` - - `SepCore.Runtime.UIModule.asmref` - - `SepCore.Presentation.UIModule.asmref` -2. 将 `Assets/Plugins/UIModule/Prefab/DialogForm.prefab` 复制到: - - `Assets/GameMain/UI/UIForms` -3. 处理原有 Dialog 资源(任选其一): - - 重命名旧 `DialogForm` 资源,或 - - 确认无引用后删除旧 `DialogForm` 资源 -4. 在 `Launcher` 场景的 `Customs` 下创建对象并挂载 `UIRouterComponent` - ---- - -## 3. UIRouter 配置 - -`UIRouterComponent` 通过 Inspector 配置 `UIFormType -> Controller` 映射: - -- `UI Form Type` -- `Controller Type` - -编辑器会扫描所有实现 `IUIFormController` 的**可实例化类型**(非抽象、非接口、非开放泛型)。 -运行时 `Awake()` 会自动注册配置项。 - -当前 Router 对外接口: - -- `BindUIUseCase(UIFormType uiFormType, IUIUseCase useCase)` -- `OpenUIAsync(UIFormType uiFormType, object userData = null, float timeout = 30f)` -- `CloseUIAsync(UIFormType uiFormType, object userData = null, float timeout = 30f)` - -说明: - -- 缺少 Controller 绑定时会输出 `Error` 并直接失败 -- 不会 fallback 到原始 `GameEntry.UI.OpenUIForm(...)` -- 重新注册同一 `UIFormType` 时,旧 Controller 会异步关闭并被新配置覆盖 - ---- - -## 4. 当前运行时结构 - -### 4.1 基础抽象 - -`IUIFormController` 当前是 **async-first** 接口: - -```csharp -UniTask OpenUIAsync(object userData = null, float timeout = 30f); -UniTask CloseUIAsync(object userData = null, float timeout = 30f); -void BindUseCase(IUIUseCase useCase); -``` - -`UIFormControllerBase` 当前只提供**薄机制层**能力: - -- `OpenFormAsync(TContext context, float timeout = 30f)` -- `CloseFormAsync(object userData = null, float timeout = 30f)` - -它负责: - -- 调用 `GameEntry.UI.OpenUIFormAsync(...) / CloseUIFormAsync(...)` -- 维护 `_context / _form / _formSerialId` -- 在打开后调用 `RefreshUI` -- 在打开 / 关闭时订阅与解除 `SubscribeCustomEvents()` - -它**不负责**: - -- 解析 `userData` -- 构造 `Context` -- 缓存业务回调 -- 安排子类的业务时序 - -这些流程由具体 Controller 显式实现。 - -### 4.2 UGF 异步适配 - -插件的 async 行为并没有改 UGF 底层事件机制,而是通过以下适配层桥接: - -- `AsyncTaskHelper` -- `UIAsyncExtension` - -其中 `UIAsyncExtension` 目前已支持: - -- `OpenUIFormAsync(string uiFormAssetName, string uiGroupName, ...)` -- `OpenUIFormAsync(int uiFormId, object userData = null, float timeout = 30f)` -- `CloseUIFormAsync(int serialId, object userData = null, float timeout = 30f)` - ---- - -## 5. Controller 实现约定 - -当前推荐写法是: - -1. 子类自己在 `OpenUIAsync(...)` 里: - - 校验 `userData` - - 构造 `RawData / Context` - - 缓存本次交互需要的临时状态 - - `await OpenFormAsync(...)` -2. 子类自己在 `CloseUIAsync(...)` 里: - - 清理本次交互缓存 - - `await CloseFormAsync(...)` -3. 基类只提供共用开关窗机制,不隐藏业务时序 - -也就是说,实现 Controller 时,应该尽量做到: - -- **看子类本身就能看懂完整流程** -- 不依赖“阅读基类钩子调用顺序”来推断业务时机 - ---- - -## 6. Dialog 当前实现 - -### 6.1 相关类型 - -- `DialogRawData`(`SepCore.UI`) - - 外部输入模型 - - 可携带: - - 标题 / 内容 / 按钮文本 - - `PauseGame` - - `OnClickConfirm / OnClickCancel / OnClickOther` - - `UserData` - -- `DialogContext`(`SepCore.UIModule`) - - 纯展示数据 - - 不携带回调 - -- `DialogController`(`SepCore.UIModule`) - - 显式实现 `OpenUIAsync / CloseUIAsync` - - 负责缓存按钮回调与 `UserData` - - 负责把 `DialogRawData` 转成 `DialogContext` - -- `DialogForm`(`SepCore.UIModule`) - - 只负责渲染和派发 UI 专用事件 - -- `DialogEventArgs`(`SepCore.Event`) - - 当前 Dialog 只使用**一个事件类型** - - 通过 `ButtonId` 区分按钮: - - `1`:Confirm - - `2`:Cancel - - `3`:Other - -### 6.2 当前数据流 - -1. 外部调用: - - ```csharp - await uiRouter.OpenUIAsync(UIFormType.DialogForm, rawData); - ``` - -2. `DialogController.OpenUIAsync(...)`: - - 校验 `DialogRawData` - - 构造 `DialogContext` - - 缓存按钮回调和 `UserData` - - `await OpenFormAsync(context, timeout)` - -3. `DialogForm` 在按钮点击时只发出: - - - `DialogEventArgs.Create(1, null)` - - `DialogEventArgs.Create(2, null)` - - `DialogEventArgs.Create(3, null)` - -4. `DialogController` 收到 `DialogEventArgs` 后根据 `ButtonId` 选出对应回调 - -5. `DialogController` 调用异步关闭流程,再执行回调: - - `await CloseUIAsync()` - - `callback?.Invoke(userData)` - -6. `CloseUIAsync()` 会先清理缓存,再交给基类关闭 UI - -### 6.3 当前限制 - -- `DialogController.OpenUIAsync(null)` 会失败并输出 warning -- Dialog 当前**不依赖 UseCase** -- `DialogForm` 当前没有本地化默认文本回退: - - 标题、正文、按钮文本都以 `DialogRawData` 传入值为准 - ---- - -## 7. 注意点 - -1. **先注册再打开** - 使用前需确保 `UIRouterComponent` 已完成 `Awake` 自动注册。 - -2. **Controller 必须绑定且可实例化** - 缺少绑定时 Router 直接失败,不会回退到原生打开路径。 - -3. **统一走 async 接口** - 启用 UIModule 管理的 UI,应统一通过: - - `OpenUIAsync(...)` - - `CloseUIAsync(...)` - -4. **Controller 负责显式业务流程** - 基类只提供开关窗机制;`userData` 校验、`Context` 构造、回调缓存与关闭后的后续动作都应在具体 Controller 中明确写出。 - -5. **保持依赖方向** - - `SepCore.Base`:UI 专用事件 - - `SepCore.Runtime`:UI 基础抽象、`RawData`、`UseCase`、`UIRouterComponent` - - `SepCore.Presentation`:Controller、Context、View - -6. **Prefab 脚本一致性** - Dialog prefab 上必须挂载插件内 `SepCore.UIModule.DialogForm`。 - -7. **Dialog 事件语义** - 当前 Dialog 使用单一 `DialogEventArgs` + `ButtonId` 区分按钮,不再使用多个按钮事件类型。 - -8. **Dialog 当前按单实例思路使用** - `DialogController` 当前没有额外用 `sender` / `serialId` 做多实例过滤,默认按单实例 Dialog 使用。 diff --git a/Assets/Plugins/UIModule/docs/UIModule-使用说明.md.meta b/Assets/Plugins/UIModule/docs/UIModule-使用说明.md.meta deleted file mode 100644 index 700a5de..0000000 --- a/Assets/Plugins/UIModule/docs/UIModule-使用说明.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 8f6066a06979f654fab6ac54a688cbfb -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: