Skip to content

ADR-066: 全屏资源库界面(精简版)

状态: ✅ 已实施(Phase 1-4) 日期: 2026-07-08 关联: ADR-034(菜单统一)、ADR-045(统一加载) 恢复/记忆行为: 见上层汇总 ADR-097(模型记忆优先 + 文件夹记忆回退,统一恢复链路)


问题

slideRow 纯文本行(~36px 高)无法显示缩略图;模型库纯文字列表用户无法快速识别模型外观。

目标:可选全屏/半屏资源浏览模式,缩略图网格展示,与 SlideMenu 侧边栏共存。


方案选择

方案结论
A: 扩展 slideRow 加缩略图❌ 行高固定无法显示有意义预览
B: 全屏 Overlay + 独立网格⚠️ 工作量大,独立导航逻辑
C: SlideMenu 内嵌 renderCustom⚠️ 宽度固定~320px,全屏体验差
D: 可切换面板(推荐)✅ 渐进式(嵌入→全屏),复用 SlideMenu 导航

架构要点

三模式状态机

CLOSED → [点击网格按钮] → EMBEDDED_GRID(侧边栏内)
  → [点击展开] → FULLSCREEN(position:fixed,SlideMenu冻结)
  → [Escape/点击背景/关闭] → EMBEDDED_GRID
  → [点击列表] → CLOSED(恢复slideRow列表)

关键:全屏时 SlideMenu DOM 不销毁仅隐藏,关闭时原样恢复。

导航集成

ResourcePanel 不维护独立导航状态,所有导航操作通过 CustomEvent 冒泡到 SlideMenu:

ts
// ResourcePanel 内部
container.dispatchEvent(new CustomEvent('enterFolder', { detail: { path } }));
container.dispatchEvent(new CustomEvent('back', { detail: {} }));
// SlideMenu 监听
container.addEventListener('enterFolder', (e) => stack.push(buildLevel(...)));

视图切换保留 filter

ts
function switchViewMode(mode: 'grid' | 'list'): void {
    const currentFilter = currentLevel?.filter;
    replaceCurrentLevel(buildLevel(currentLevel.dir, currentLevel.label, currentFilter));
}

虚拟滚动

IntersectionObserver + 占位元素,只渲染可见行 ± 1 行缓冲,500+ 模型时 DOM 节点可控。


组件接口

ts
interface ResourcePanelOptions {
    items: LibraryModel[];
    thumbnailCache: Map<string, string>;
    onSelect: (model: LibraryModel) => void;
    layout?: 'grid' | 'list';
    columns?: number;
}

实施路线

Phase内容
Phase 1ui-resource-panel.ts 基础网格 + IntersectionObserver 懒加载
Phase 2ui-virtual-grid.ts 虚拟滚动 + library-core 集成 + 视图切换
Phase 3ui-fullscreen-overlay.ts 全屏容器 + SlideMenu 冻结/恢复
Phase 4缩略图预加载 + 视图模式持久化 + 搜索集成

风险与缓解

风险缓解
全屏与 SlideMenu 状态同步DOM 不销毁,仅隐藏/显示
视图切换丢失 filterbuildLevel 传递 filter 参数
移动端适配响应式列数:320px→2列,768px→4列,1024px→6列
缩略图未生成fallback 到 Iconify 图标