cloud-drive-renamer/docs/superpowers/specs/2026-03-20-preview-panel-option-a-design.md

245 行
9.2 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

# 预览面板 Option A 设计
## 背景
当前预览面板已经具备以下能力:
- 统计预览项数量、冲突数量与执行状态。
- 按状态高亮冲突、失败、成功、待执行项目。
- 在长列表场景下使用虚拟列表优化渲染性能。
但当前实现仍有一个明显的确认断点:用户在预览区只能看到**新文件名**,无法直接看到对应的**旧文件名**。这会导致用户在执行前需要依赖记忆完成确认,尤其在以下场景下体验较差:
1. 文件名格式相近,只靠新名称无法分辨来源。
2. 剧集提取、正则替换等规则会对多个文件同时生效,用户需要确认映射是否正确。
3. 冲突和失败项虽然有状态提示,但用户无法第一时间知道“是哪一个原文件会出问题”。
与 `docs/renamer.js` 的对比中,这也是最容易被用户感知到的交互差距。因此本次选择采用 **Option A:在不改变整体三栏布局的前提下,为每条预览项补充“旧名 -> 新名”对照信息**。
## 目标
- 在不重做整体布局的前提下,补齐预览项的“旧名 -> 新名”映射展示。
- 保持当前三栏布局与信息密度,不引入更重的审阅台模型。
- 让冲突项、失败项的可理解性提升,不需要用户额外点开详情或回到文件列表反查。
- 尽量复用现有 `PreviewItem` 数据结构和 `virtual-preview-list` 渲染链路,降低改动面。
## 非目标
- 不在本次改动中引入单条操作按钮,例如“排除”“仅重试此项”“从此项填充剧名”等。
- 不将预览区改造成完整的“变更审阅中心”。
- 不调整当前执行流程、冲突检测流程或批量执行引擎。
- 不新增新的规则类型或剧集提取逻辑。
## 方案对比
### 方案 A:双行映射预览(采用)
- 每条预览项显示:
- 第一行:旧文件名 + 当前状态
- 第二行:新文件名 + 方向箭头
- 第三行:仅在必要时显示补充说明,例如冲突原因、失败原因或提取结果提示
**优点**
- 最大收益来自补足确认链路,而不是重做布局。
- 可以直接复用当前的 `PreviewItem.file.name` 与 `PreviewItem.newName`。
- 改动集中在展示层,风险较低。
- 与现有三栏布局兼容,不会显著压缩左右两栏可用空间。
**缺点**
- 单条项目高度会增加,列表可视密度略低于当前实现。
- 视觉表达力不如更重的“审阅台”方案。
### 方案 B:变更审阅视图
- 每条项目除旧名、新名外,还显式展示规则来源、风险标签、操作建议。
**优点**
- 表达力更强,后续可自然承接单条操作入口。
**缺点**
- 单项高度更大,长列表滚动负担更高。
- 需要重新设计预览面板层级,超出本轮“低风险优化”的目标。
**采用方案:A。**
## 交互设计
### 1. 面板整体结构
保留当前右侧预览面板结构:
1. 标题区
2. 统计区
3. 列表区
不改变面板层级,只调整列表项视觉结构。
### 2. 预览项结构
每条预览项调整为三层信息:
#### 第一层:旧文件名
- 使用较弱的视觉层级展示原文件名。
- 文本颜色弱于新文件名,但仍需足够可读。
- 右侧保留状态标签,例如:
- `成功`
- `待执行`
- `冲突`
- `失败`
#### 第二层:新文件名
- 使用较强视觉层级展示新文件名。
- 保持当前预览区域的主阅读焦点。
- 可在最右侧加入轻量箭头,强调“从旧名映射到新名”。
#### 第三层:补充信息
- 仅在需要时展示,避免噪声。
- 建议场景:
- 剧集提取成功时:显示提取结果摘要,如 `剧集提取 / 季号 01 / 集号 003`
- 冲突时:显示“与现有文件名重复”
- 失败时:显示可读性更强的原因文案,而不是裸错误码
### 3. 状态表达
保留当前背景色与左侧强调边的状态表达方式:
- `success`:浅绿色背景
- `warning/conflict`:浅橙色背景
- `error`:浅红色背景
- `pending`:中性背景
但状态标签需要从“附属角标”升级为“与旧名同行的信息”,这样用户先看到旧文件,再看到它当前是否有风险。
### 4. 长文件名处理
- 旧文件名与新文件名均保留单行截断。
- `title` 保持完整名称悬浮提示。
- 对失败原因仍使用一行或两行受控显示,避免把列表高度拉得过长。
### 5. 空状态与加载状态
沿用当前空状态和 loading 状态,不做额外改动。
## 架构与组件设计
### 涉及组件
- `[src/content/components/preview-panel.ts](/Users/lhly/chromeex/cloud-drive-renamer/src/content/components/preview-panel.ts)`
- `[src/content/components/virtual-preview-list.ts](/Users/lhly/chromeex/cloud-drive-renamer/src/content/components/virtual-preview-list.ts)`
- `[src/types/file-selector.ts](/Users/lhly/chromeex/cloud-drive-renamer/src/types/file-selector.ts)`
- `[src/locales/zh_CN.json](/Users/lhly/chromeex/cloud-drive-renamer/src/locales/zh_CN.json)`
- `[src/locales/zh_TW.json](/Users/lhly/chromeex/cloud-drive-renamer/src/locales/zh_TW.json)`
- `[src/locales/en.json](/Users/lhly/chromeex/cloud-drive-renamer/src/locales/en.json)`
### 数据结构
本方案优先不修改 `PreviewItem` 结构,因为现有数据已足够:
- `item.file.name`:旧文件名
- `item.newName`:新文件名
- `item.conflict`:是否冲突
- `item.done`:是否成功
- `item.error`:失败原因
如需增加更友好的说明文案,优先在展示层通过状态推导生成,不新增持久化字段。
### 渲染职责
#### `preview-panel`
- 继续负责统计区与外层容器。
- 不承担单项结构逻辑,避免组件职责继续膨胀。
#### `virtual-preview-list`
- 负责预览项的双行映射展示。
- 继续承担虚拟滚动切换逻辑。
- 负责把原始状态值转换成最终的显示块结构。
## 文案设计
### 推荐新增文案键
- `preview_old_name`
- `preview_new_name`
- `preview_mapping_arrow`
- `preview_conflict_reason_existing_name`
- `preview_extract_summary`
- `preview_failed_reason_prefix`
如果实现时认为标签文本过多,也可以不引入“旧名/新名”显式标题,而仅通过层级和箭头表达映射关系,以减少视觉拥挤。
### 错误文案策略
当前失败项可能直接显示错误码,例如 `extract_episode_not_found`。在本方案中建议:
- UI 层优先转成面向用户的可读文案;
- 保留原始错误码作为 `title` 或调试信息;
- 避免在主列表里直接暴露生硬内部标识。
## 数据流
### 现有流程
1. `file-selector-panel` 根据规则生成 `previewList`
2. `preview-panel` 接收 `items`
3. `virtual-preview-list` 渲染每个 `PreviewItem`
### 方案 A 调整后
数据流保持不变,仅增强最后一步渲染:
1. `file-selector-panel` 无需新增字段
2. `preview-panel` 无需新增协议
3. `virtual-preview-list` 从 `item.file.name` 和 `item.newName` 生成双行映射视图
这意味着本次改动主要是视图层优化,而非状态管理或执行流程改造。
## 风险与权衡
### 1. 列表可视密度下降
双行结构会使单项高度增加。考虑到预览区已经支持虚拟列表,这个问题可接受,但需要控制补充信息的默认展示长度。
### 2. 样式复杂度提升
当前预览项样式较简单,双行结构会增加样式层级。需要确保:
- 状态色仍然清晰;
- 旧名不会抢走新名焦点;
- 不引入与现有主题变量冲突的新颜色体系。
### 3. 国际化文案膨胀
若补充标签过多,会增加 i18n 维护成本。实现时应优先使用结构和层级表达含义,而不是堆更多标题文本。
## 测试设计
### 1. 组件渲染测试
针对 `virtual-preview-list` 增加测试,验证:
- 成功项会同时展示旧名和新名。
- 冲突项会显示冲突状态和冲突说明。
- 失败项会显示失败状态和失败说明。
- `showStatus = false/true` 时状态展示符合预期。
### 2. 截断与 title 测试
验证长文件名情况下:
- 旧名、新名都不会撑破布局;
- 完整名称仍能通过 `title` 获取。
### 3. 视觉回归检查
建议补一个组件级快照或 Playwright 截图验证,至少覆盖:
- 普通项
- 成功项
- 冲突项
- 失败项
### 4. 虚拟列表兼容性
确认增加双行结构后,虚拟列表的初始化与刷新逻辑不受影响,尤其是超过 200 条项目时的滚动与渲染稳定性。
## 实施建议
### 第一阶段
- 仅修改 `virtual-preview-list` 渲染结构和样式。
- 保持 `preview-panel` 统计区不变。
- 保持数据结构不变。
### 第二阶段(可选)
- 视实际效果决定是否在补充信息中加入更友好的失败原因翻译。
- 若用户反馈仍希望进一步增强,可再演进到更强的审阅视图,而不是一次性做重。
## 结论
Option A 是一次典型的“高感知、低侵入”优化:
- 它不解决所有预览场景问题;
- 但它能直接补足当前最明显的确认断点;
- 且几乎不需要改动执行逻辑、状态管理和数据结构。
因此本次建议按 **展示层局部升级** 的方式推进,先把“旧名 -> 新名”的确认能力补齐,再根据真实反馈决定是否继续向更重的审阅模型演进。