# 页面与视图结构(Gio) > 本项目是 Gio 桌面应用,没有 URL 路由;本文约定页面(视图)划分、职责和组件归属。现代版与 Win7 版共享 ViewModel 和交互语义,Gio 控件实现允许分别适配。 ## 主窗口布局 ```text ┌─────────────────────────────────────────────┐ │ 顶部栏:搜索框 · 分类筛选 · 检测更新 · 下载队列入口 │ ├────────┬────────────────────────────────────┤ │ 左侧 │ 中部:虚拟化软件列表(layout.List) │ │ 视图 │ 每项:图标·名称·版本·状态·进度·主操作按钮 │ │ 全部 │ │ │ 已安装 │ 右侧/弹层:软件详情 │ │ 可更新 │ 版本 · 简介 · 安全诊断 · 状态 · 操作 │ │ 最近使用│ │ ├────────┴────────────────────────────────────┤ │ 底部状态栏:网络 · 任务数 · 磁盘 · 盒子版本(Legacy 标识) │ └─────────────────────────────────────────────┘ ``` ## 视图清单 | 视图 | 职责 | MVP | | --- | --- | --- | | 软件列表(主视图) | T-203 已实现全部/已安装/可更新切换、名称/ID/tag 即时搜索、单分类筛选、稳定滚动与明确空状态;下载中/最近使用和多标签复选随对应用例后续接入 | P0 | | 软件详情(弹层或右栏) | T-204 已实现右栏、关闭、版本/分类/简介/tags/状态/不可用原因/教程/主页展示与内存图标;T-611 仅对当前 `unsafe_cache` 显示稳定安全诊断和人工恢复提示;真实操作和授权事实随对应模块接入 | P0 | | 下载队列 | 所有任务的进度、速度、剩余时间;暂停/取消/重试 | P0 | | 设置 | 并发数、目录、代理、自动检查更新、beta 通道、日志级别、便携模式(V2) | P0(最小集) | | 授权 | 许可证导入、已授权软件列表、machine 信息、换绑/申诉入口 | P0 | | 提示/错误弹窗 | 失败原因、重试路径、更新确认、退出运行中软件提示 | P0 | ## 组件归属 | 组件 | 归属 | 说明 | | --- | --- | --- | | AppShell | 全局 | 窗口框架、顶部栏、左侧导航、底部状态栏 | | AppList | 主视图 | 惰性 `layout.List`;控件状态按软件 ID 保存,不按列表序号 | | AppRow | 主视图 | 单个软件项:状态、进度和主操作按钮 | | AppDetail | 详情 | 详情展示与操作 | | DownloadPanel | 下载队列 | 任务列表与控制 | | SettingsForm | 设置 | 设置项读写(经 application 用例) | | LicensePanel | 授权 | 导入与状态展示 | | Toast/Dialog | 全局 | 错误与确认交互 | T-610 固定 modern 与 Win7 两个 `ui/gio` 适配器的同 package 文件职责;文件名镜像,但不跨 workspace 共享 Gio 代码: | 文件 | 职责 | | --- | --- | | `shell.go` | `AppShell` 状态/构造、`SetItems`/`ApplyIcon` 生命周期、根 `Layout` 与输入 drain | | `shell_header.go` | 顶部栏、分类、view/filter 导航与版本特有 footer | | `shell_catalog.go` | content/catalog、惰性列表、app row/icon 与空状态 | | `shell_detail.go` | 详情布局、详情字段、`unsafe_cache` 安全诊断与动作/回退文案 helper | | `shell_style.go` | palette/theme、panel 绘制、view/status 文案与颜色 helper | 这些文件仍共同实现一个 `gio` package,不是新增页面 API 或状态层。modern-only 的 `layoutCatalog`/`layoutFooter`/`actionLabel` 等保留在对应职责文件,Win7 不增加空壳;后续视图应进入相应职责文件,不能重新把布局链堆回根 `shell.go`。 每个页面用独立 struct 保存:`widget.Clickable`、`widget.Editor`、`layout.List`、过滤条件、当前 ViewModel、pending RequestID、临时提示和错误状态。 ## 交互规则(硬约束) - 每帧先 drain application relay 与点击事件,再提交用例;后台只把事件放入有界 relay 并调用并发安全的 `Window.Invalidate`,Frame/UI goroutine 在 `ApplyEvent` 中更新 ViewModel/ImageOp。 - Layout 中不得读磁盘、访问网络、计算哈希;图标走内存 + 磁盘缓存(按 DPI)。 - 数百个软件项滚动不卡顿是验收标准,不是优化项。 - 未验证/不兼容的软件显示原因,操作按钮禁用,不静默失败。 - Win7 版允许减少动画、阴影和高成本渲染,但交互语义与现代版一致,并明显展示 Legacy 标识。 T-203 已落地的列表交互约束: - 共享 `core/application.CatalogListModel` 只消费预先准备的内存快照;搜索覆盖名称、稳定 ID 和 tags,分类与 all/installed/updates 可组合。 - modern/win7 都使用惰性 `layout.List`;500 项有限 viewport 测试必须证明不会布局全部行。 - Editor、视图按钮、分类按钮、软件行的键盘顺序与视觉顺序一致;搜索和软件行有可见焦点反馈,所有按钮最小高度 44dp。 - 行 Clickable 保存在以 app ID 为键的 map;筛选、视图切换或 Catalog 快照更新不按可见序号迁移控件状态。 - 无 Catalog 与过滤无结果是两个不同空状态;后者提供“显示全部软件”恢复操作。 T-608 用 modern/win7 同场景适配器契约固定上述接线:Editor 和视图/分类/行/恢复/关闭 Clickable 必须经 `Layout`/`drainInput` 更新共享 model;Catalog 重排后行事件仍按 AppID 选择,关闭详情保留筛选与 list First/Offset。500 项有限 viewport 同时核对实际布局计数与 `layout.List.Position.Count`;空 Catalog、过滤无结果及恢复按钮通过 Gio 语义树区分。两端测试只在 edition/窗口尺寸上保留真实差异,不互相 import Gio。 T-609 固定 `VisibleItems()` 的只读 snapshot generation:筛选或 Catalog 变化时由 model 完整构造新 backing array 后发布,已被上一帧持有的旧 generation 保持稳定;同一 generation 的每帧读取不复制。两个 Gio 适配仍只在 UI owner goroutine 读取,不得修改返回 slice、item 或 Tags,该契约不提供并发读写安全。 T-616 固定启动快照投递:`cmd` 只在后台运行 `CatalogBootstrap`,它将已准备内存快照或稳定失败 code 发布到 runtime;relay 后的 UI Frame 通过 `ApplyEvent` 更新 shell。初始 loading、`catalog_source_unconfigured`、`catalog_load_failed`、已加载空 Catalog 和筛选无结果必须有不同的可见文本,错误不清除已加载快照。当前没有可信发布配置时,只能显示未配置诊断,不能从 testdata、环境变量、任意 URL、未签名本地文件或 allow-all verifier 生成列表;任何这些 I/O/校验仍不得进入 Layout。 T-204 已落地的详情/图标约束: - 点击软件行用 selected app ID 打开右侧详情,关闭后回到同一列表/筛选/滚动上下文。 - modern 与 Legacy 均显示版本、分类、简介、tags、状态、不可用原因、教程和主页文本;尚未接入的安装/启动/授权不伪装为已可执行操作。 - T-607 由 `IconEventDelivery` 在后台完成可信加载/解码并发布强类型 `IconReady`/`IconFailed`;有界 FIFO relay 只请求 Invalidate,Frame/UI goroutine drain 后才调用 `ApplyEvent`/`ApplyIcon`。相同 app 只接受最新且 IconRef/DPI 匹配的 request_id;Catalog 删除、IconRef 变化或取消后丢弃迟到结果,IconRef 变化同时清除旧 ImageOp。 - 图标未命中或离线缓存不可用时显示非 emoji 的字母占位,不阻塞列表或详情。 - T-611 将最近一次已验证失败保存为完整 `IconEventIdentity + IconFailureCode`;新请求、匹配 ready、IconRef/DPI 变化、取消和 app 删除清除旧诊断,同引用 Catalog snapshot 可保留。只有 `unsafe_cache` 在当前选中详情显示文字告警、`unsafe_cache`、app ID 与 `-.icon` locator;`unavailable`/`invalid_content` 保持普通占位,不冒充安全事件。 - 安全告警必须有可访问标题、明确说明本次未继续远端获取/自动修复并指向 [故障排查](troubleshooting.md);颜色不能作为唯一信号,不得增加清理、隔离或重试按钮,不得显示绝对路径、原始 error、URL/query 或 link target。 ## 导航规则 - 列表 → 详情:点击软件项;详情保留返回/关闭。 - 任一视图可进下载队列(顶部入口);任务完成后返回时列表状态已回填。 - 启动需授权的软件而无有效许可证时,引导到授权视图,不直接报错退出。 - 更新需要退出运行中的软件时,弹确认对话框,等待用户处理,超时取消更新。