界面基础目录与按需数据准备
本文面向维护者,说明界面如何判断英雄/地图目录是否可信、何时自动准备结构化数据,以及页面、 任务门禁和进度如何保持一致。
1. 三类不同状态
共享目录流程必须与另外两类状态分开:
- 任务快照:执行中心创建任务时冻结的参数。后续修改设置不会改写已入队任务。
- 运行时配置:用于构造后续
AppContext的游戏目录、输出目录和区域等共享设置。 - 共享实体数据:英雄、地图与可选特殊内容的结构化目录,供主页、执行中心和实体总览共同 使用。
个性化设置(主题、平滑滚动、日志抽屉等)不属于共享目录上下文,不触发目录重建。 “提前准备数据”影响扫描要求,属于共享目录配置签名;保存在 [gui] prepare_data_on_startup, 默认关闭,切换后重新检查当前目录。
2. 单一事实来源
SharedDataController 持有当前 SharedDataState,页面不得再根据中文消息、日志内容或 worker 是否正常结束推断就绪状态。
一次完整扫描由 SharedDataScanWorker 在后台运行,内部调用 EntityDataLoader.scan_catalog(),返回一个 SharedDataScanResult。该结果同时包含:
- 当前
generation和版本; - 英雄、地图、特殊内容三个 section;
- 每个 section 的权威 expected IDs、成功 rows、失败项与未准备项;
- 按稳定问题码聚合的
problems; - 由必需目录事实派生的 complete、partial 或 failed readiness。
逐实体异常可以被扫描器收集后继续扫描,但不能只写日志并丢弃。英雄或地图 expected 集合为空、 Map 0 缺失、任一必需 ID 未形成有效行,都不能进入 ready。
默认扫描只要求基础清单可读,尚无资源绑定的普通实体保留“未准备”行,可以选择并创建任务。 已有有效绑定时继续展示真实音频、映射状态;未准备对象的音频预览为空,不触发 BIN 解析。 仅在开启提前准备时,缺失/旧版/不完整的资源绑定和缺失/过期事件缓存才成为共享扫描阻断项。
结构化特殊内容和显式 resource pack 是可选目录。它们未准备不会降低普通英雄/地图的 readiness;默认共享扫描也不会遍历全部历史 FINAL WAD。
3. 状态机
| Phase | 含义 | 阻止新任务 |
|---|---|---|
blocked | 必要配置缺失或无效 | 是 |
checking | 正在建立上下文或完整扫描 | 是 |
waiting | 配置已变更,等待现有任务队列结束 | 是 |
preparing | 正在准备基础目录,或按开启的偏好准备完整资源 | 是 |
verifying | update 完成,正在重建 reader 并完整复检 | 是 |
ready | 必需英雄与地图通过当前 generation 对应扫描模式的复检 | 否 |
partial | 有可信 rows,但必需目录不完整 | 是 |
failed | 无法形成可信必需目录或准备失败 | 是 |
cancelled | 准备被权威结果标记为取消 | 是 |
active、blocks_new_tasks 和语义角色都由 phase 派生。只有 ready 可以创建新任务或把总览选择 发送到执行中心;partial 可以浏览已经验证成功的 rows,但页面持续显示目录不完整状态。
每次 reader 相关配置变化都会增加 generation。旧 worker 的 scan、prepare、failure 和 progress 回调在应用前检查 generation,不允许覆盖新上下文。
4. 检查、准备与复检
首次启动、手动刷新、配置变化和显式重试共用同一条主链:
- 校验必要配置并异步建立
AppContext。 - 完整扫描当前目录。
- complete 时原子发布三类 rows,再发布
ready。 - 若全部阻断问题都可自动修复,按失败证据生成 repair scope。
- 每个 generation 最多自动准备一次;默认仅调用
prepare_update_data(),开启提前准备时调用 普通update(),均默认force_update=False。 - 消费 update 返回的真实
StageResult。 - success 或 partial 时重建读取上下文并完整复检;failed/cancelled 直接进入对应终态。
- 复检 complete 且准备结果不是 partial 时才能进入
ready。
自动可修复问题包括数据缺失/过期/为空、banks 缺失、local resource schema 不兼容、binding 不完整、 Map 0 缺失和可分类的 artifact 损坏。配置、权限或来源不可用不会触发自动循环。
默认共享 readiness 不要求 banks/events;开启提前准备后同时检查两者,以覆盖用户先仅解包、之后 再开启提前准备的情况。最终 mapping 产物不属于就绪条件。当前版本的有效缓存不重建,已成功 解析但没有事件的地图也保存空事件缓存,避免把“没有事件”误判为“未准备”。
| 用户任务 | 准备规则 |
|---|---|
| 解包或映射 | worker 内对所选范围执行普通 update,转发真实进度 |
| 仅映射 | 设置 process_events=True |
| 解包与映射组合 | 共用准备过程与运行时上下文 |
| 显式前置强制更新 | 使用强制更新流程 |
| 公共 BIN 与合同 | 保留 Map 0、特殊英雄、v2 binding;缓存齐全的地图不重复预处理公共 BIN |
| 单纯 WAV 转码或导出 | 不触发 BIN 准备 |
自动准备成功不作为用户音频产物阶段参与最终状态聚合,避免依赖检查成功把后续全失败伪装成 部分成功;非成功准备结果保留在任务报告中。failed/cancelled 阻止后续消费,partial 保留逐对象 问题并继续尝试可处理对象。
普通更新后同类可修复问题仍存在时,主页提供“重新生成实体数据”。这是用户显式选择的二级恢复, 才会使用 force_update=True;初次自动迁移不会删除旧文件或默认 force。结构化 artifact 仍通过 同目录临时文件和原子替换发布,失败时保留原文件。
5. StageResult 与扫描各自证明什么
update 的 StageResult 证明准备过程的执行事实,完整扫描证明界面目录的可读事实,两者缺一不可:
- success:进入 verifying,不直接显示成功;
- partial:仍进行复检以发布实际 rows,但最终至少为 partial;
- failed:直接 failed,不调用成功重载路径;
- cancelled:直接 cancelled,不显示 100% 或成功通知。
worker finished 只表示后台函数返回。进度达到 total 只表示当前阶段已处理完,都不能替代上述 typed 结果。
6. 进度与全局所有权
核心 update 通过可选 OperationProgress 回调发布 data、champion_banks 和 map_banks 阶段; 完整扫描通过 SharedDataProgress 发布 champions、special 和 maps 阶段。
- total 未知的上下文建立或短阶段使用不确定动画,不显示虚构百分比或 ETA。
- total 已知时,主页与全局宿主消费同一份归一化 current/total 快照;填充宽度直接跟随真实比值。
- 普通进度在控制器边界以 50 ms 窗口保留最新值,阶段 started/finished 和终态立即发布。
- 进度回调不等待 UI 绘制,实体总览也不会因每个计数更新而重建目录模型。
| 进度宿主 | 规则 |
|---|---|
| 用户任务与共享准备重叠 | 用户任务优先;保存共享状态,任务结束后仅恢复最新 generation 的共享进度 |
| 共享准备 | 不进入用户任务队列,不显示用户任务取消按钮 |
| 主页 | 共享状态已有页内进度,隐藏同源全局条;仍活跃时保留底部布局占位,避免切页改变内容高度 |
| 其他页面 | 立即恢复共享全局条 |
| 用户任务全局条 | 不受主页对共享进度的抑制影响 |
7. 页面与恢复动作
- 主页:显示 phase、动态英雄/地图摘要、单一确定或不确定进度条,以及稳定恢复按钮;计数只在 实体状态卡中出现一次。
- 执行中心:只有 ready 启用创建任务;活跃阶段显示“准备数据中”,waiting 显示“等待当前任务 结束”,其余终态保留原因 Tooltip。
- 实体总览:活跃阶段显示加载占位;partial 保留 verified rows,但禁用“发送到执行中心”。
- 全局进度:除主页外,用户切换标签页后继续展示共享准备状态。
恢复动作使用稳定 action key,由窗口层绑定真实行为:
- 配置缺失/无效、输出不可写:打开全局设置;
- 可修复问题:重试更新;普通迁移后仍失败时可重新生成;
- 来源不可用或未分类错误:先提供重试,日志只作为补充诊断。
通知只提示有意义的状态转折。普通启动直接 ready 不弹成功通知;自动准备开始、准备并复检成功、 initial partial/failed 各按 generation 去重。持久页面状态始终是主要反馈。
8. 队列与刷新边界
运行时配置在队列仍有等待或运行任务时进入 waiting。已有任务继续使用创建时的上下文快照,设置页 锁定后端相关分组;队列清空后,控制器自动继续新 generation 的 checking。
任务完成后的产物增量刷新与共享 readiness 分离:它只按 EntityResult.artifacts 更新已有目录行, 不会把 partial/failed 变成 ready,也不会触发共享自动准备。强制终止拿不到可靠产物快照时不做猜测性 刷新。
9. 验证边界
自动化测试覆盖 phase 映射、完整/部分/失败扫描、Map 0、可选 special、一次自动准备、StageResult 四态、generation 拒旧、队列 waiting、进度模式/节流、恢复动作、ready-only 门禁,以及旧 schema 经 普通 update adapter 后复检为 ready。
布局、颜色、缩放、键盘可达性和主观流畅度不使用像素或源码字面量测试。它们保留在原生 Windows 界面人工验收,通过标准入口 uv run unpack-gui 检查。
共享进度 mock
需要反复检查首页页内进度与其他页面底部全局进度时,先正常启动界面,打开全局日志抽屉后按住 Ctrl 点击日志标题,进入开发控制台。输入下列命令即可启动只作用于展示层的循环 mock:
shared progress默认每 50 ms 前进一步,依次模拟 checking、英雄更新、地图更新、英雄复检、地图复检和 ready; 一轮结束后自动重新开始。需要放慢观察时可指定 10–2000 ms 的步进间隔:
shared progress 80再次执行 shared progress <interval_ms> 会按新速度重新开始;shared inspect 查看运行状态, shared stop 停止并恢复最新真实状态。
mock 不会读取、扫描、更新或写入真实实体数据。它只覆盖首页共享状态和底部全局进度条,不改变执行 中心的真实数据与任务门禁;真实共享状态再次发布时,mock 会自动停止,避免遮蔽后台事实。