Files
workutils/docs/superpowers/specs/2026-07-31-public-ui-foundation-design.md
T
2026-07-31 18:57:30 +08:00

8.6 KiB
Raw Blame History

公共 UI 基础能力收尾设计

日期:2026-07-31

目标

收拢生成、扫描和同步类插件中重复的通知、结果文件操作、任务状态展示与无障碍语义,使窗口只负责组合界面和业务用例。重构后,常见交互具有一致行为,公共代码可以独立测试,AI 修改单个插件时不需要复制或猜测平台相关实现。

本阶段不改变业务流程、输出格式和历史数据格式。

范围

本阶段实施

  • 新增统一通知入口,首批迁移 MyBatis 生成器和 Git 同步。
  • 统一 API 文档、Scanner、MyBatis SQL 导出的历史文件操作。
  • 修正 SQL 导出状态栏的无效停止按钮。
  • 加强 ExportHistoryPane、EmptyStatePane、OperationStatusPane 的键盘、焦点和屏幕阅读器语义。
  • 为 ScanProgress、SqlExportProgress 增加输入约束和稳定的展示转换。
  • 增加单元测试、组件测试和架构约束测试。

明确不实施

  • Git 评审的弹窗或窗口重构。
  • 手机 UI 自动化窗口的任何重构。
  • 系统设置和插件管理窗口迁移到新通知能力。
  • 全局视觉主题、配色和窗口布局重做。
  • 为进度 DTO 引入统一继承层次或通用事件总线。
  • 把 Diff 剪贴板操作并入历史文件操作。

设计原则

  1. 窗口不直接处理操作系统文件打开、编辑、目录定位或剪贴板细节。
  2. 公共服务通过窄接口注入,测试不启动外部程序、不写系统剪贴板。
  3. 通知文案由调用方表达业务含义,通知中心只负责展示方式和线程安全。
  4. 只有底层任务具有真实取消能力时才展示停止按钮。
  5. 不为了“统一”创建不能降低调用复杂度的抽象。

组件设计

1. NotificationCenter

在 system.ui.notification 下新增:

  • NotificationCenter:窗口可依赖的接口。
  • FxNotificationCenter:JavaFX 实现,绑定 owner,并集中创建对话框。
  • NotificationMessage:不可变通知数据,包含级别、标题、正文;构造时拒绝空正文。

接口提供:

  • info(title, message)
  • warning(title, message)
  • error(title, message)
  • confirm(title, header, message),返回是否确认

普通通知允许从任意线程调用;实现会调度到 JavaFX Application Thread。确认对话框必须在 JavaFX Application Thread 调用,因为它需要同步返回用户选择;违反约束时立即抛出带说明的异常,避免后台线程静默阻塞或死锁。

FxNotificationCenter 负责 owner、默认标题、可复制长文本和一致的关闭行为。长结果仍可使用可调整大小的文本对话框,但由通知中心实现,不再由 MyBatis 窗口自行创建 Stage。

首批调用方:

  • MyBatis 生成器:查询/生成警告、生成结果、生成前确认。
  • Git 同步:缺失远程地址警告、批量重新拉取确认。

Git 同步中“删除目录后重新 clone”的危险说明必须原样保留;本轮只替换展示机制。

2. ResultFileActions

在 system.ui.history 下新增:

  • FileActionGateway:open、edit、reveal、copyPath 四个操作。
  • SystemFileActionGateway:使用 SystemOpenHelper 和 JavaFX Clipboard 的生产实现。
  • ResultFileActions:路径校验、异常转换、统一通知和成功反馈。

ResultFileActions 可生成现有 HistoryFileCommands,因此 ExportHistoryPane 不需要知道操作系统能力,也不需要改变对外构造协议。调用方可以传入一个可选的成功消息消费者,将“已复制路径”等信息写入自己的日志区;失败统一交给 NotificationCenter。

路径规则:

  • 空路径:不调用网关,显示明确错误。
  • 打开或编辑:目标必须是存在的普通文件。
  • 定位目录:目标文件存在时定位该文件;目标已不存在时不得猜测父目录,显示错误。
  • 复制路径:复制规范化绝对路径;目标不存在时仍允许复制,以便排查历史记录,但反馈中说明目标不存在。

API 文档、Scanner、MyBatis SQL 导出删除各自的 openFile、openWithNotepad、openFolder 和剪贴板代码,改为在窗口初始化时创建一次共享命令对象。

3. 进度与取消语义

保留领域 DTO,不增加通用进度接口:

  • ScanProgress:正文不可为空;进度必须是 -1(不确定)或 [0, 1]。
  • SqlExportProgress:current、total、recordCount 不得为负,current 不得大于 total,项目名不可为空;fraction() 保持在 [0, 1]。

DTO 只表达领域进度。窗口通过小型纯函数把 DTO 转换为 OperationSnapshot 所需的 message 和 fraction,转换函数独立测试。

Scanner 已明确不可取消,保持不显示停止按钮。MyBatis SQL 导出的用例没有中断协议,本轮把 OperationStatusPane 的 cancellable 显式设为 false。不增加表面上可点击、实际上不能停止数据库或文件操作的按钮。

4. 公共组件无障碍语义

ExportHistoryPane:

  • “打开”“目录”按钮设置明确的 accessible text;tooltip 作为补充而非唯一说明。
  • 右键菜单保留,同时支持表格行获得焦点后通过键盘打开文件。
  • 行为空时清除 tooltip、accessible text 和旧行引用,避免 TableCell 复用泄漏上一个条目。
  • 操作失败后焦点留在触发控件,不强制跳转。

EmptyStatePane:

  • 容器使用可读的无障碍角色描述。
  • 标题和说明组合为完整 accessible text。
  • 有操作按钮时,按钮进入正常 Tab 顺序;无操作时容器不抢占键盘焦点。

OperationStatusPane:

  • 进度条和状态文案设置 accessible text。
  • 状态变化时同步可读文本,不只依赖颜色表达成功或失败。
  • 不可取消时,不创建可聚焦的停止按钮;可取消时只在运行阶段显示并进入 Tab 顺序。

本阶段用代码语义和现有主题常量检查颜色使用,不进行全主题颜色重做。若发现现有公共组件直接使用低对比硬编码颜色,只在该组件内修正。

数据与调用流

文件操作流程:

ExportHistoryPane -> HistoryFileCommands -> ResultFileActions -> FileActionGateway

其中 ResultFileActions 负责验证和错误翻译,网关只执行平台动作。窗口只提供 owner 和可选日志消费者。

通知流程:

Window / ResultFileActions -> NotificationCenter -> JavaFX dialog

业务异常在最接近业务语境的调用方转换成用户文案;通知中心不解析异常、不拼接业务名称,也不记录敏感值。

错误处理

  • 公共服务捕获平台操作的已知运行时异常,展示稳定的中文动作描述,并保留异常消息作为附加信息。
  • 不吞掉编程错误:空依赖、非法 DTO 和错误线程上的确认调用立即失败。
  • 通知内容不得包含数据源密码、令牌或带凭据的远程 URL。
  • Git 重新拉取的删除与 clone 逻辑不移动到通知中心,也不因弹窗重构改变执行顺序。

测试策略

单元测试

  • ResultFileActionsTest:四种委托、空路径、文件不存在、网关异常、复制不存在路径及成功反馈。
  • NotificationMessageTest:字段规范化和非法输入。
  • 进度 DTO 测试:边界值、非法值和 fraction。
  • 进度展示转换测试:初始、中间、结束及记录数文案。

JavaFX 组件测试

  • ExportHistoryPane 的按钮、tooltip、accessible text、键盘触发和 TableCell 复用清理。
  • EmptyStatePane 的无操作/有操作焦点行为。
  • OperationStatusPane 的可取消与不可取消结构、状态文字和可见性。

架构约束

  • API 文档、Scanner、MyBatis SQL 导出不得直接调用 SystemOpenHelper 或 JavaFX Clipboard。
  • MyBatis 生成器和 Git 同步不得直接创建 Alert。
  • 排除项不纳入此约束,避免本阶段误改 Git 评审、手机 UI 自动化、系统设置。

验收

  • 全量 Maven 测试通过。
  • Maven compile 通过。
  • git diff --check 通过。
  • 只读 UI 冒烟检查确认三个历史列表、MyBatis 生成确认/结果和 Git 同步确认仍可正常交互。
  • 不启动文件、编辑器、资源管理器或危险 Git 重拉操作来完成自动化验证;平台动作由测试替身验证。

实施顺序

  1. 先以测试定义通知接口及线程约束,再实现并迁移两个窗口。
  2. 以测试定义文件动作规则,再迁移三个历史窗口。
  3. 补强进度 DTO,修正 SQL 导出取消语义。
  4. 补齐三个公共组件的无障碍行为。
  5. 运行架构测试、全量验证和只读 UI 验收。

每一步保持可独立编译和回滚,不把未完成的半套公共接口留给后续步骤。