设计公共 UI 基础能力收尾
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
# 公共 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 验收。
|
||||
|
||||
每一步保持可独立编译和回滚,不把未完成的半套公共接口留给后续步骤。
|
||||
Reference in New Issue
Block a user