feat: 增强桌面启动失败提示与测试覆盖
This commit is contained in:
@@ -6,6 +6,130 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Desktop 启动失败报告
|
||||
|
||||
Desktop SHALL 将无法进入可用状态的启动失败统一转换为包含阶段、用户消息和底层原因的启动错误,并通过统一报告器提示用户。
|
||||
|
||||
#### Scenario: 配置加载或验证失败
|
||||
|
||||
- **WHEN** desktop 启动时 `~/.nex/config.yaml` 无法解析或配置验证失败
|
||||
- **THEN** 系统 SHALL 生成 `config` 阶段启动错误
|
||||
- **THEN** 错误提示 SHALL 包含配置文件路径和失败原因
|
||||
- **THEN** 应用 SHALL 退出
|
||||
|
||||
#### Scenario: 日志初始化失败
|
||||
|
||||
- **WHEN** desktop 启动时完整 logger 初始化失败
|
||||
- **THEN** 系统 SHALL 生成 `logger` 阶段启动错误
|
||||
- **THEN** 错误提示 SHALL 描述日志初始化失败并包含可操作的路径或权限线索
|
||||
- **THEN** 应用 SHALL 退出
|
||||
|
||||
#### Scenario: 数据库初始化或迁移失败
|
||||
|
||||
- **WHEN** desktop 启动时数据库打开、连接、初始化或迁移失败
|
||||
- **THEN** 系统 SHALL 生成 `database` 或 `migration` 阶段启动错误
|
||||
- **THEN** 错误提示 SHALL 描述数据库初始化失败或迁移失败
|
||||
- **THEN** 错误提示 SHALL NOT 暴露 MySQL password、完整 DSN 或 API key 等敏感信息
|
||||
- **THEN** 应用 SHALL 退出
|
||||
|
||||
#### Scenario: 嵌入资源或内部组件初始化失败
|
||||
|
||||
- **WHEN** desktop 启动时前端嵌入资源、协议 adapter 或其他内部组件初始化失败
|
||||
- **THEN** 系统 SHALL 生成对应启动阶段的启动错误
|
||||
- **THEN** 错误提示 SHALL 描述应用初始化失败并建议查看日志或重新安装
|
||||
- **THEN** 应用 SHALL 退出
|
||||
|
||||
#### Scenario: 启动失败提示降级链
|
||||
|
||||
- **WHEN** desktop 生成 fatal 启动错误
|
||||
- **THEN** 系统 SHALL 先尝试平台系统通知
|
||||
- **THEN** 系统 SHALL 在通知不可用或返回失败时尝试平台模态弹窗
|
||||
- **THEN** 系统 SHALL 在模态弹窗不可用或返回失败时输出到 stderr 或可用启动日志
|
||||
- **THEN** 每一次提示通道失败 SHALL 被记录但 SHALL NOT 阻止后续 fallback
|
||||
|
||||
#### Scenario: 提示通道调用前可用性检查
|
||||
|
||||
- **WHEN** desktop 启动失败报告器准备调用任一系统通知或模态弹窗通道
|
||||
- **THEN** 系统 SHALL 在调用前检查该通道对应命令、系统 API 或图形会话条件是否可用
|
||||
- **THEN** 系统 SHALL 在通道不可用时跳过该通道并进入下一 fallback
|
||||
- **THEN** 系统 SHALL NOT 因某个通知或弹窗工具缺失而中断后续降级链
|
||||
|
||||
#### Scenario: 浏览器打开失败为非 fatal
|
||||
|
||||
- **WHEN** desktop 后端服务和托盘已启动但浏览器自动打开失败
|
||||
- **THEN** 系统 SHALL 记录 warning
|
||||
- **THEN** 系统 SHALL 尝试通过非 fatal 提示告知用户可手动访问 `http://localhost:<server.port>`
|
||||
- **THEN** 应用 SHALL 继续运行
|
||||
|
||||
### Requirement: macOS 通知和对话框降级策略
|
||||
|
||||
系统 SHALL 在 macOS 上优先使用通知中心提示 desktop 启动错误,并在通知不可用时降级到 AppleScript 模态告警。
|
||||
|
||||
#### Scenario: macOS 通知可用
|
||||
|
||||
- **WHEN** desktop 在 macOS 上生成启动错误且通知命令可用
|
||||
- **THEN** 系统 SHALL 使用 `osascript display notification` 发送系统通知
|
||||
- **THEN** 通知 SHALL 包含应用名称和错误描述文本
|
||||
|
||||
#### Scenario: macOS 通知失败
|
||||
|
||||
- **WHEN** macOS 系统通知命令不可用或返回失败
|
||||
- **THEN** 系统 SHALL 使用 `osascript display alert` 显示模态告警
|
||||
- **THEN** 模态告警 SHALL 使用 critical 错误语义
|
||||
- **THEN** 告警 SHALL 包含应用名称和错误描述文本
|
||||
|
||||
#### Scenario: macOS UI 提示均失败
|
||||
|
||||
- **WHEN** macOS 系统通知和模态告警均失败
|
||||
- **THEN** 系统 SHALL 降级输出到 stderr 或可用启动日志
|
||||
|
||||
### Requirement: Linux 启动错误提示降级策略
|
||||
|
||||
系统 SHALL 在 Linux 上为 desktop 启动错误按优先级使用可用的通知或对话框工具,优先使用系统通知栏,再降级到模态弹窗,最后降级到标准错误输出。该策略 SHALL 不移除既有通用信息提示能力。
|
||||
|
||||
#### Scenario: notify-send 可用
|
||||
|
||||
- **WHEN** desktop 在 Linux 上生成启动错误且 `notify-send` 命令可用并存在图形会话
|
||||
- **THEN** 使用 `notify-send` 显示系统通知
|
||||
- **AND** 错误通知使用 `-u critical` 参数
|
||||
- **AND** 通知 SHALL 包含应用名称和错误描述文本
|
||||
|
||||
#### Scenario: kdialog passive popup 可用
|
||||
|
||||
- **WHEN** `notify-send` 不可用或返回失败且 `kdialog` 命令可用
|
||||
- **THEN** 系统 SHALL 优先尝试使用 `kdialog --passivepopup` 显示系统通知式提示
|
||||
|
||||
#### Scenario: zenity 可用
|
||||
|
||||
- **WHEN** Linux 通知工具不可用或返回失败且系统检测到 `zenity` 命令可用
|
||||
- **THEN** 使用 zenity 显示 GTK 风格错误对话框
|
||||
- **AND** 错误对话框使用 `zenity --error` 命令
|
||||
|
||||
#### Scenario: kdialog 模态对话框可用
|
||||
|
||||
- **WHEN** `zenity` 不可用或返回失败且 `kdialog` 命令可用
|
||||
- **THEN** 使用 kdialog 显示 KDE 风格错误对话框
|
||||
- **AND** 错误对话框使用 `kdialog --error` 命令
|
||||
|
||||
#### Scenario: xmessage 可用
|
||||
|
||||
- **WHEN** `zenity`、`kdialog` 模态对话框均不可用或返回失败且 `xmessage` 命令可用
|
||||
- **THEN** 使用 xmessage 显示基础 X11 对话框
|
||||
- **AND** 对话框居中显示(`-center` 参数)
|
||||
|
||||
#### Scenario: 无 UI 工具可用
|
||||
|
||||
- **WHEN** 所有通知和对话框工具均不可用、图形会话不存在或所有 UI 提示均返回失败
|
||||
- **THEN** 降级到标准错误输出
|
||||
- **AND** 输出格式为 `错误: <title>: <message>`
|
||||
|
||||
#### Scenario: 工具检测缓存
|
||||
|
||||
- **WHEN** desktop 在 Linux 上启动
|
||||
- **THEN** 系统检测一次可用通知和对话框工具
|
||||
- **AND** 检测结果缓存在包级变量
|
||||
- **AND** 后续提示调用直接使用缓存结果,不重复检测
|
||||
|
||||
### Requirement: 桌面应用启动
|
||||
|
||||
系统 SHALL 支持作为桌面应用启动,将后端服务与前端静态资源打包为单一可执行文件,并使用启动配置中的 `server.port` 作为本次运行端口。
|
||||
@@ -36,7 +160,7 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
|
||||
### Requirement: 系统托盘
|
||||
|
||||
系统 SHALL 提供跨平台系统托盘功能,支持托盘图标和菜单。图标格式 SHALL 根据平台自动选择,端口显示 SHALL 使用启动配置中的 `server.port`。
|
||||
系统 SHALL 提供跨平台系统托盘功能,支持托盘图标和菜单。图标格式 SHALL 根据平台自动选择,端口显示 SHALL 使用启动配置中的 `server.port`。托盘初始化失败 SHALL 被视为 desktop fatal 启动失败。
|
||||
|
||||
#### Scenario: 托盘图标显示
|
||||
|
||||
@@ -60,11 +184,19 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
- **WHEN** 用户点击托盘菜单"打开管理界面"
|
||||
- **THEN** 系统在浏览器中打开 `http://localhost:<server.port>`
|
||||
|
||||
#### Scenario: 托盘 ready 后自动打开浏览器
|
||||
|
||||
- **WHEN** desktop 启动并完成托盘图标、菜单和点击事件初始化
|
||||
- **THEN** 系统 SHALL 将托盘标记为 ready
|
||||
- **THEN** 系统 SHALL 在托盘 ready 后自动打开 `http://localhost:<server.port>`
|
||||
- **THEN** 系统 SHALL NOT 在托盘初始化失败时自动打开浏览器
|
||||
|
||||
#### Scenario: 浏览器打开失败
|
||||
|
||||
- **WHEN** 系统无法打开浏览器(浏览器未安装等)
|
||||
- **THEN** 托盘菜单仍可正常使用
|
||||
- **AND** 用户可手动访问 `http://localhost:<server.port>`
|
||||
- **AND** 系统 SHALL 尝试显示非 fatal 提示,告知用户手动访问地址
|
||||
|
||||
#### Scenario: 退出应用
|
||||
|
||||
@@ -73,6 +205,13 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
- **AND** 托盘图标消失
|
||||
- **AND** 应用进程退出
|
||||
|
||||
#### Scenario: 托盘初始化失败
|
||||
|
||||
- **WHEN** desktop 启动时托盘未在限定时间内 ready、托盘图标资源无法加载或托盘菜单无法完成初始化
|
||||
- **THEN** 系统 SHALL 生成 `tray` 阶段启动错误
|
||||
- **THEN** 系统 SHALL 通过启动失败提示降级链提示用户
|
||||
- **THEN** 应用 SHALL 退出
|
||||
|
||||
### Requirement: 静态文件服务
|
||||
|
||||
系统 SHALL 通过 Gin 同时服务 API、协议代理和前端静态资源。
|
||||
@@ -126,19 +265,28 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
|
||||
### Requirement: 端口冲突检测
|
||||
|
||||
系统 SHALL 在启动前检测启动配置中的 `server.port` 是否可用。
|
||||
系统 SHALL 在启动时获取启动配置中的 `server.port` 对应监听端口,并使用同一个 listener 启动后端服务,避免端口预检测与实际监听之间的竞态。
|
||||
|
||||
#### Scenario: 配置端口可用
|
||||
|
||||
- **WHEN** 启动配置中的 `server.port` 未被占用
|
||||
- **THEN** 服务正常启动
|
||||
- **THEN** 系统 SHALL 成功创建该端口的 listener
|
||||
- **THEN** 后端服务 SHALL 使用该 listener 正常启动
|
||||
|
||||
#### Scenario: 配置端口被占用
|
||||
|
||||
- **WHEN** 启动配置中的 `server.port` 已被其他程序占用
|
||||
- **THEN** 显示错误提示"端口 <server.port> 已被占用"
|
||||
- **THEN** 系统 SHALL 生成 `port` 阶段启动错误
|
||||
- **THEN** 错误提示 SHALL 包含"端口 <server.port> 已被占用"
|
||||
- **AND** 应用退出
|
||||
|
||||
#### Scenario: 单实例优先于端口监听
|
||||
|
||||
- **WHEN** 用户尝试启动第二个 desktop 实例
|
||||
- **THEN** 系统 SHALL 优先检测到已有实例持有文件锁
|
||||
- **THEN** 系统 SHALL 显示"已有 Nex 实例运行"相关错误提示
|
||||
- **THEN** 系统 SHALL NOT 将该场景误报为端口占用
|
||||
|
||||
### Requirement: 桌面配置源隔离和启动快照
|
||||
|
||||
desktop SHALL 仅在启动时从默认配置文件 `~/.nex/config.yaml` 和默认值加载运行时配置,并将加载结果作为本次运行的 immutable runtime snapshot。
|
||||
@@ -312,74 +460,52 @@ desktop 内嵌前端 SHALL 使用同源相对路径访问后端 API,不主动
|
||||
|
||||
### Requirement: Windows 原生对话框
|
||||
|
||||
系统 SHALL 在 Windows 上使用 `user32.dll` 的 `MessageBoxW` API 显示错误对话框,替代 `msg *` 命令。
|
||||
系统 SHALL 在 Windows 上优先使用系统通知提示启动错误,并在通知不可用或失败时使用 `user32.dll` 的 `MessageBoxW` API 显示错误对话框,替代 `msg *` 命令。
|
||||
|
||||
#### Scenario: Windows 通知优先
|
||||
|
||||
- **WHEN** 应用在 Windows 上遇到启动错误(端口占用、配置加载失败等)
|
||||
- **THEN** 系统 SHALL 优先尝试发送 Windows 系统通知
|
||||
- **THEN** 通知 SHALL 包含应用名称和错误描述文本
|
||||
|
||||
#### Scenario: 错误提示对话框
|
||||
|
||||
- **WHEN** 应用在 Windows 上遇到启动错误(端口占用、配置加载失败等)
|
||||
- **WHEN** Windows 系统通知不可用或返回失败
|
||||
- **THEN** 使用 `MessageBoxW` 显示模态对话框
|
||||
- **AND** 对话框标题栏显示应用名称
|
||||
- **AND** 对话框包含错误描述文本
|
||||
- **AND** 对话框显示错误图标(MB_ICONERROR)
|
||||
- **AND** 对话框 SHALL 尽量置于前台或顶层显示
|
||||
|
||||
#### Scenario: Windows UI 提示均失败
|
||||
|
||||
- **WHEN** Windows 系统通知和 `MessageBoxW` 均失败
|
||||
- **THEN** 系统 SHALL 记录提示失败原因
|
||||
- **THEN** 系统 SHALL 降级输出到可用启动日志
|
||||
|
||||
#### Scenario: 非 Windows 平台不受影响
|
||||
|
||||
- **WHEN** 应用运行在 macOS 或 Linux 上
|
||||
- **THEN** 错误对话框仍使用平台原有实现(osascript / zenity)
|
||||
|
||||
### Requirement: Linux 对话框降级策略
|
||||
|
||||
系统 SHALL 在 Linux 上按优先级检测并使用可用的对话框工具,确保在不同桌面环境下都能显示对话框。
|
||||
|
||||
#### Scenario: zenity 可用
|
||||
- **WHEN** 系统检测到 `zenity` 命令可用
|
||||
- **THEN** 使用 zenity 显示 GTK 风格对话框
|
||||
- **AND** 错误对话框使用 `zenity --error` 命令
|
||||
- **AND** 信息对话框使用 `zenity --info` 命令
|
||||
|
||||
#### Scenario: kdialog 可用
|
||||
- **WHEN** zenity 不可用且 `kdialog` 命令可用
|
||||
- **THEN** 使用 kdialog 显示 KDE 风格对话框
|
||||
- **AND** 错误对话框使用 `kdialog --error` 命令
|
||||
- **AND** 信息对话框使用 `kdialog --msgbox` 命令
|
||||
|
||||
#### Scenario: notify-send 可用
|
||||
- **WHEN** zenity 和 kdialog 均不可用且 `notify-send` 命令可用
|
||||
- **THEN** 使用 notify-send 显示系统通知
|
||||
- **AND** 错误通知使用 `-u critical` 参数
|
||||
- **AND** 信息通知使用默认参数
|
||||
|
||||
#### Scenario: xmessage 可用
|
||||
- **WHEN** zenity、kdialog、notify-send 均不可用且 `xmessage` 命令可用
|
||||
- **THEN** 使用 xmessage 显示基础 X11 对话框
|
||||
- **AND** 对话框居中显示(`-center` 参数)
|
||||
|
||||
#### Scenario: 无对话框工具可用
|
||||
- **WHEN** 所有对话框工具均不可用
|
||||
- **THEN** 降级到标准错误输出
|
||||
- **AND** 输出格式为 `错误: <title>: <message>`
|
||||
|
||||
#### Scenario: 工具检测缓存
|
||||
- **WHEN** 应用启动
|
||||
- **THEN** 系统检测一次可用对话框工具
|
||||
- **AND** 检测结果缓存在包级变量
|
||||
- **AND** 后续对话框调用直接使用缓存结果,不重复检测
|
||||
- **THEN** 错误提示 SHALL 使用对应平台的通知和弹窗降级策略
|
||||
|
||||
### Requirement: macOS AppleScript 字符转义
|
||||
|
||||
系统 SHALL 对 AppleScript 对话框中的特殊字符进行转义,确保脚本正确执行。
|
||||
系统 SHALL 对 AppleScript 通知、模态告警和对话框中的特殊字符进行转义,确保脚本正确执行。
|
||||
|
||||
#### Scenario: 转义反斜杠
|
||||
- **WHEN** 对话框消息包含反斜杠字符 `\`
|
||||
|
||||
- **WHEN** AppleScript 提示文本包含反斜杠字符 `\`
|
||||
- **THEN** 转义为 `\\`
|
||||
|
||||
#### Scenario: 转义双引号
|
||||
- **WHEN** 对话框消息包含双引号字符 `"`
|
||||
|
||||
- **WHEN** AppleScript 提示文本包含双引号字符 `"`
|
||||
- **THEN** 转义为 `\"`
|
||||
|
||||
#### Scenario: 多行文本处理
|
||||
- **WHEN** 对话框消息包含换行符 `\n`
|
||||
- **THEN** AppleScript 正确显示多行文本
|
||||
|
||||
- **WHEN** AppleScript 提示文本包含换行符 `\n`
|
||||
- **THEN** AppleScript 通知或模态告警 SHALL 正确显示多行文本或保留可读换行语义
|
||||
|
||||
### Requirement: 桌面应用打包迁移资源
|
||||
|
||||
|
||||
Reference in New Issue
Block a user