Files
SecScore/.trae/documents/url-registration-robustness.md
T
Yukino_fox a2ec923788 feat(URL协议): 增强URL协议注册健壮性
- 新增check_url_protocol_status命令检测注册状态
- 新增unregister_url_protocol命令取消注册
- 改进register_url_protocol命令增加验证逻辑
- 前端增加状态检测、自动重试和操作日志功能
- 更新多语言翻译支持新功能
2026-05-04 12:11:18 +08:00

9.5 KiB
Raw Blame History

URL 协议注册健壮性增强计划

目标

为 SecScore 的 URL 协议注册功能实现完整的健壮性增强,包括:状态检测、注册验证、自动重试(最多7次)、按钮状态自动切换、取消注册、以及全流程日志记录。


涉及文件

文件 操作 说明
src-tauri/src/commands/app.rs 修改 新增 check_url_protocol_statusunregister_url_protocol 命令;增强 register_url_protocol
src-tauri/src/lib.rs 修改 注册新命令到 invoke_handler
src/preload/types.ts 修改 新增 API 类型定义
src/components/Settings.tsx 修改 重写 URL 协议 UI,加入状态显示、重试逻辑、按钮切换
src/i18n/locales/*.json (10个) 修改 新增 i18n 翻译键

步骤 1Rust 后端 - 新增 UrlProtocolStatus 结构体和 check_url_protocol_status 命令

文件: src-tauri/src/commands/app.rs

1.1 新增结构体

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UrlProtocolStatus {
    pub registered: bool,
    pub protocol: String,
    pub platform: String,
    pub details: String,
}

1.2 实现 check_url_protocol_status 命令

按平台实现 URL 协议状态检测:

  • Windows: 查询注册表 HKCU\Software\Classes\secscore 是否存在,检查 URL Protocol 值和 shell\open\command 中的路径是否指向当前 exe

  • macOS:

    1. 先尝试通过 lsregister -dump 查询 secscore:// scheme 的注册状态
    2. 检查 ~/Library/LaunchAgents/com.secscore.url-handler.plist 是否存在(非 .app bundle 场景)
  • Linux:

    1. 检查 ~/.local/share/applications/secscore.desktop 是否存在且包含 x-scheme-handler/secscore
    2. 通过 xdg-settings get default-url-scheme-handler secscore 验证是否为默认处理器

返回 UrlProtocolStatus 结构体,包含注册状态、当前平台、检测详情。


步骤 2Rust 后端 - 新增 unregister_url_protocol 命令

文件: src-tauri/src/commands/app.rs

按平台实现取消注册:

  • Windows: 删除注册表 HKCU\Software\Classes\secscore 键 (reg delete "HKCU\Software\Classes\secscore" /f)

  • macOS:

    1. 如果存在 .app bundle,通过 lsregister -u 取消注册
    2. 删除 ~/Library/LaunchAgents/com.secscore.url-handler.plist
  • Linux:

    1. 删除 ~/.local/share/applications/secscore.desktop
    2. 运行 update-desktop-database

步骤 3Rust 后端 - 增强 register_url_protocol 命令

文件: src-tauri/src/commands/app.rs

改造现有 register_url_protocol

  1. 执行注册操作后,不再盲目返回 registered: Some(true)
  2. 注册完成后,自动调用状态检测逻辑验证注册是否成功
  3. 返回实际检测到的注册状态(registered 字段反映真实结果)
  4. 在每个关键步骤添加 eprintln! 日志输出(Rust 端日志)

步骤 4:Rust 后端 - 注册新命令

文件: src-tauri/src/lib.rs

invoke_handler 中添加:

  • check_url_protocol_status

  • unregister_url_protocol


步骤 5:前端 API 类型定义

文件: src/preload/types.ts

新增 API 方法:

checkUrlProtocolStatus: (): Promise<{
  success: boolean
  data?: {
    registered: boolean
    protocol: string
    platform: string
    details: string
  }
  message?: string
}> => invoke("check_url_protocol_status"),

unregisterUrlProtocol: (): Promise<{
  success: boolean
  data?: { registered: boolean }
  message?: string
}> => invoke("unregister_url_protocol"),

步骤 6:前端 Settings.tsx - 重写 URL 协议卡片 UI

文件: src/components/Settings.tsx

6.1 新增状态变量

const [urlStatus, setUrlStatus] = useState<{ registered: boolean; details: string } | null>(null)
const [urlStatusLoading, setUrlStatusLoading] = useState(false)
const [urlOperationLogs, setUrlOperationLogs] = useState<string[]>([])

6.2 状态检测逻辑

  • 组件加载 URL tab 时自动执行一次 checkUrlProtocolStatus

  • 在 UI 中显示当前注册状态(Tag: 已注册/未注册 + 详情文本)

6.3 注册流程(含自动重试)

handleRegister():
  1. 记录日志:"开始注册 URL 协议..."
  2. 调用 registerUrlProtocol()
  3. 记录日志:"注册命令已执行,开始验证..."
  4. 调用 checkUrlProtocolStatus() 验证
  5. IF 注册成功:
     - 记录日志:"注册验证成功"
     - 更新状态显示
     - 完成
  6. ELSE (注册失败):
     - FOR retry = 1 TO 7:
       - 记录日志:"注册失败,第 {retry}/7 次重试..."
       - 延迟 retry * 1000 ms (递增延迟: 1s, 2s, 3s, ..., 7s)
       - 调用 registerUrlProtocol()
       - 调用 checkUrlProtocolStatus() 验证
       - IF 成功:
         - 记录日志:"第 {retry} 次重试成功"
         - 更新状态,退出循环
       - ELSE:
         - 记录日志:"第 {retry} 次重试失败"
     - IF 7次全部失败:
       - 记录日志:"已达最大重试次数(7次),注册失败"
       - 显示错误消息

6.4 按钮状态自动切换

根据 urlStatus.registered 动态渲染:

状态 按钮文本 按钮类型 点击行为
未注册 "注册 URL 协议" primary 执行注册(含重试)
已注册 "重新注册" default 执行注册(覆盖注册+验证)
已注册 "取消注册" danger 执行 unregisterUrlProtocol + 验证

6.5 操作日志展示

在 URL 协议卡片底部增加一个可折叠的 <Collapse> 或简洁的 <Typography.Paragraph> 区域,展示最近的操作日志(最多保留最新 20 条),使用 fontSize: 12px, fontFamily: monospace 样式。


步骤 7i18n 翻译

文件: src/i18n/locales/ 下所有 10 个语言文件

settings.url 下新增以下键:

zh-CN en-US
checkStatus "检测状态" "Check Status"
reRegister "重新注册" "Re-register"
unregister "取消注册" "Unregister"
unregistered "URL 协议已取消注册" "URL protocol unregistered"
unregisterFailed "取消注册失败" "Failed to unregister"
statusRegistered "已注册" "Registered"
statusNotRegistered "未注册" "Not Registered"
statusCheckFailed "状态检测失败" "Status check failed"
retrying "重试中 ({current}/{max})" "Retrying ({current}/{max})"
retryFailed "已达最大重试次数,注册失败" "Max retries reached, registration failed"
retrySuccess "第 {n} 次重试成功" "Retry #{n} succeeded"
operationLog "操作日志" "Operation Log"
logRegisterStart "开始注册 URL 协议..." "Starting URL protocol registration..."
logRegisterVerify "注册命令已执行,正在验证..." "Registration command executed, verifying..."
logRegisterSuccess "注册验证成功" "Registration verified successfully"
logRegisterFailed "注册验证失败" "Registration verification failed"
logUnregisterStart "正在取消注册..." "Unregistering..."
logUnregisterSuccess "取消注册成功" "Unregistered successfully"
logUnregisterFailed "取消注册失败" "Unregister failed"
logMaxRetries "已达最大重试次数 (7次)" "Max retries (7) reached"

其余 9 个语言文件同步翻译。


步骤 8:运行测试与格式化

  1. 执行 pnpm run typecheck(如有)检查前端类型
  2. 执行 cargo check 检查 Rust 编译
  3. 执行格式化命令
  4. 运行测试套件

实现顺序

  1. 步骤 1Rust - check_url_protocol_status
  2. 步骤 2Rust - unregister_url_protocol
  3. 步骤 3Rust - 增强 register_url_protocol
  4. 步骤 4Rust - 注册新命令到 lib.rs
  5. 步骤 5:前端 API 类型
  6. 步骤 6:前端 Settings.tsx UI
  7. 步骤 7i18n 翻译
  8. 步骤 8:测试与格式化