Files
FlowScope/docs/requirements/p0-uimanager.md
2026-05-15 15:38:40 +08:00

4.0 KiB
Raw Blame History

P0-8: UIManager 需求详细文档

对齐说明

本文档以 docs/requirements/p0-requirements-set.md 为准。P0 UIManager 支持可配置层级和层内 LIFO 栈,但不做完整导航路由系统。UIPanelAttribute 明确包含 path 参数。

目标

提供 MVVM Panel 生命周期管理、运行时层级注册、层内栈式打开关闭、手写 Bind/Unbind 和基础缓存/销毁策略。

层级注册

public sealed class UIManager
{
    public void RegisterLayer(
        string name,
        Canvas canvas,
        int sortOrder,
        PanelStrategy strategy = PanelStrategy.Destroy);
}

public enum PanelStrategy
{
    Destroy,
    Cache
}

规则:

  • P0 不强制固定 Bottom/Middle/Top
  • 推荐默认层级为 background / hud / popup / dialog / system
  • 项目可只注册部分层级。
  • 未注册层级打开 Panel 时抛异常。

Panel Attribute

[AttributeUsage(AttributeTargets.Class)]
public sealed class UIPanelAttribute : Attribute
{
    public string Layer { get; }
    public string Path { get; }
    public PanelStrategy? OverrideStrategy { get; }

    public UIPanelAttribute(
        string layer,
        string path = null,
        PanelStrategy? overrideStrategy = null)
    {
        Layer = layer;
        Path = path;
        OverrideStrategy = overrideStrategy;
    }
}

规则:

  • Layer 必填。
  • Path 可选;未填时按命名约定推导。
  • OverrideStrategy 可选,优先于层级默认策略。

Panel 基类

public abstract class UIPanelBase<TViewModel> : MonoBehaviour
{
    protected TViewModel ViewModel { get; private set; }
    protected CompositeDisposable Disposables { get; } = new();

    public void Bind(TViewModel viewModel)
    {
        ViewModel = viewModel;
        OnBind(viewModel);
    }

    public virtual void Unbind()
    {
        Disposables.Clear();
    }

    protected abstract void OnBind(TViewModel viewModel);
}

打开与关闭接口

public sealed class UIManager
{
    public Task<TPanel> OpenAsync<TPanel, TViewModel>(
        TViewModel viewModel,
        CancellationToken cancellationToken)
        where TPanel : UIPanelBase<TViewModel>;

    public void Close<TPanel>();
    public void CloseLayer(string layerName);
    public void CloseAll();
    public bool IsOpen<TPanel>();
}

生命周期

OpenAsync:
  1. 读取 UIPanelAttribute
  2. 校验层级已注册
  3. 解析资源路径
  4. IResourceService.LoadAsync<GameObject>
  5. Instantiate 到目标 Canvas
  6. Bind(viewModel)
  7. SetActive(true)
  8. 压入层内栈

Close:
  1. 校验目标 Panel 是所在层级栈顶
  2. 从栈弹出
  3. Unbind()
  4. Destroy 策略Destroy GameObject 并释放资源 handle
  5. Cache 策略SetActive(false),保留实例和资源 handle

路径约定:

ShopPanel -> UI/Shop/Prefab
ConfirmPanel -> UI/Confirm/Prefab
MainHudPanel -> UI/MainHud/Prefab

暂不做

  • 自动 UI 绑定。
  • 导航路由系统。
  • 跨 Feature 页面恢复。
  • Panel 预加载。
  • SafeArea。
  • 多语言 UI 切换。
  • 红点/通知系统。
  • 复杂转场动画。

验收标准

# 标准 通过条件
1 注册层级 RegisterLayer 后 Panel 可挂载到对应 Canvas
2 Attribute 层级 Panel 通过 UIPanelAttribute 找到层级
3 path 参数 Attribute 指定 path 时按指定路径加载
4 路径约定 未指定 path 时按命名约定加载
5 Open 异步加载 Prefab、实例化、Bind、入栈
6 Close 栈顶 Panel Unbind 并按策略关闭
7 LIFO 关闭非栈顶 Panel 抛异常
8 Cache Cache Panel 再次打开时复用并重新 Bind
9 Destroy Destroy Panel 关闭后释放资源 handle
10 CloseLayer 只关闭指定层级
11 CloseAll 关闭所有层级
12 Bind 失败 清理已创建对象和资源 handle 后抛异常

依赖关系

UIManager
├── IResourceService
├── R3
├── Unity Canvas / GameObject / MonoBehaviour
└── CancellationToken