镜像自地址
https://github.com/lhly/search-syntax-pro.git
已同步 2026-10-20 14:27:47 +08:00
- 新增Yandex和DuckDuckGo搜索引擎适配器配置 - 更新manifest.json添加新搜索引擎权限 - 优化URL工具类支持更多搜索引擎参数解析 - 移除调试日志输出 - 修复百度搜索输入框选择器兼容性问题 - 添加文档归档和历史需求规范 版本升级至1.8.6
9.2 KiB
9.2 KiB
Requirements Confirmation Document
功能名称
Yandex 和 DuckDuckGo 悬浮按钮支持
版本信息
- 目标版本: 1.8.6
- 创建时间: 2025-12-01
- 需求质量得分: 95/100 ✅
原始需求
用户请求:
请你实施 yandex 和 duckduckgo 的悬浮按钮需求开发
需求澄清过程
第 1 轮澄清 (初始得分: 52/100)
提出的问题:
- 功能范围确认 - 是否完全复制 Baidu/Bing 的悬浮按钮功能?
- DOM 选择器配置 - 是否需要验证选择器?支持哪些域名变体?
- 边缘情况和错误处理 - 显示策略、降级方案、国际化要求
- 测试和验证 - 测试范围和类型
- 优先级和约束 - 实施顺序、发布计划
第 2 轮澄清 (最终得分: 95/100)
用户回答:
- ✅ 功能点与交互逻辑与现有悬浮按钮保持一致,只是要注意不同搜索引擎高级语法的适配有所不同
- ✅ 需要验证 DOM 选择器,暂时只支持国际版
- ✅ 仅在搜索结果页显示,DuckDuckGo 的简洁模式和完整模式都需要支持,国际化支持与扩展保持一致
- ✅ 手动测试
- ✅ 同时实施,作为新版本 1.8.6 发布
仓库上下文影响
现有基础设施
- ✅ 适配器已存在:
YandexAdapter和DuckDuckGoAdapter已完整实现 - ✅ 悬浮面板系统:
FloatingPanelManager、TriggerIcon、MessageBridge已完善 - ✅ 参考实现: Baidu 和 Bing 的悬浮按钮功能可直接复用
- ✅ 架构模式: 遵循现有的 Adapter Pattern 和 Message Protocol
技术约束
- 📦 Manifest V3: 需要更新 host_permissions 和 content_scripts
- 🎨 React + TypeScript: 遵循现有代码规范
- 🌐 i18n: 使用现有的 zh-CN/en-US 翻译系统
- ⚡ 性能: 悬浮按钮使用 transform + RAF 优化
最终确认的需求规格
功能需求
1. 核心功能(与 Baidu/Bing 完全一致)
-
可拖动悬浮按钮
- 默认位置:右下角
- 拖动使用 transform(GPU 加速)
- 位置百分比存储到 chrome.storage.local
- 窗口 resize 时响应式适配
- 拖动阈值:5px(防误触)
-
点击交互
- 点击打开高级搜索面板(iframe 模态框)
- ESC 键关闭面板
- 点击遮罩层关闭面板
-
搜索功能
- 自动填充当前搜索框内容到面板
- 根据用户配置生成高级搜索查询
- 支持"立即搜索"和"仅填充"两种模式
- 自动提交搜索表单(如果启用)
2. 关键差异点
- 语法适配
- Yandex: 使用
title:和url:代替intitle:和inurl: - Yandex: 使用
mime:代替filetype: - Yandex: 使用
|符号代替OR关键词 - Yandex: 支持独特的日期范围语法
date:YYYYMMDD..YYYYMMDD - DuckDuckGo: 标准语法(site:, filetype:, intitle:, inurl:)
- DuckDuckGo: 不支持日期范围(dateRange 功能在 UI 中禁用)
- Yandex: 使用
技术需求
1. DOM 选择器配置
需要验证并配置以下选择器(在 src/config/search-engine-selectors.ts):
// Yandex 选择器(需验证)
yandex: {
searchInputSelector: 'input[name="text"]',
searchContainerSelector: 'form.search2__form',
searchFormSelector: 'form.search2__form',
iconInsertPosition: 'afterend',
iconOffsetY: '8px',
isResultsPage: () => window.location.pathname.includes('/search')
}
// DuckDuckGo 选择器(需验证)
duckduckgo: {
searchInputSelector: 'input#search_form_input',
searchContainerSelector: 'form#search_form',
searchFormSelector: 'form#search_form',
iconInsertPosition: 'afterend',
iconOffsetY: '8px',
isResultsPage: () => window.location.search.includes('q=')
}
2. Manifest V3 配置更新
需要更新 public/manifest.json:
{
"host_permissions": [
"https://*.yandex.com/*",
"https://*.duckduckgo.com/*"
],
"content_scripts": [
{
"matches": [
"https://*.yandex.com/*",
"https://*.duckduckgo.com/*"
]
}
],
"web_accessible_resources": [
{
"matches": [
"https://*.yandex.com/*",
"https://*.duckduckgo.com/*"
]
}
]
}
3. 代码文件修改清单
- src/config/search-engine-selectors.ts: 添加 Yandex 和 DuckDuckGo 配置
- src/content/index.ts: 更新
isSearchEnginePage()检测逻辑 - src/content/FloatingPanelManager.ts: 扩展
engineKey类型定义 - public/manifest.json: 添加权限和匹配规则
边缘情况和错误处理
1. 显示策略
- ✅ 仅在搜索结果页显示: 使用
isResultsPage()检测 - ✅ DOM 加载失败: 最多重试 3 次,间隔 500ms
- ✅ 搜索框未找到: 静默失败,记录日志到 console
2. 降级方案
- ✅ DOM 选择器失败: 不显示悬浮按钮,不影响其他功能
- ✅ iframe 加载失败: 8 秒超时后自动关闭面板
- ✅ 扩展上下文失效: 捕获 "Extension context invalidated" 错误
3. 跨模式支持
- ✅ DuckDuckGo 简洁模式: 确保选择器兼容
- ✅ DuckDuckGo 完整模式: 确保选择器兼容
- ✅ Yandex 国际版: 仅支持 yandex.com(不支持 yandex.ru)
国际化需求
现有翻译复用
- ✅ 悬浮按钮提示:
content.triggerButtonTooltip - ✅ 适配器验证消息: 复用
adapter.validation.*翻译 - ✅ 错误提示: 复用现有错误消息翻译
无需新增翻译
- ✅ 所有 UI 文本使用现有 zh-CN/en-US 翻译
- ✅ 不添加俄语支持(Yandex 使用英文界面)
测试需求
手动测试清单
-
Yandex 测试
- 访问 yandex.com 搜索结果页
- 验证悬浮按钮显示在右下角
- 测试拖动功能和位置保存
- 测试点击打开面板
- 验证搜索框内容自动填充
- 测试各种高级语法组合
- 验证生成的查询 URL 正确
- 测试自动提交搜索
-
DuckDuckGo 测试
- 访问 duckduckgo.com 搜索结果页
- 验证悬浮按钮显示在右下角
- 测试拖动功能和位置保存
- 测试点击打开面板
- 验证搜索框内容自动填充
- 测试各种高级语法组合
- 验证生成的查询 URL 正确
- 测试自动提交搜索
- 测试简洁模式和完整模式兼容性
-
跨引擎测试
- 验证不同搜索引擎间位置保存独立
- 测试在不同搜索引擎间切换
- 验证扩展图标和设置页面正常工作
发布需求
版本管理
- 版本号: 1.8.6
- 更新 CHANGELOG: 记录新增功能
- 更新 README: 添加 Yandex 和 DuckDuckGo 支持说明
发布清单
- 更新
public/manifest.json版本号 - 更新
package.json版本号 - 更新 CHANGELOG.md
- 更新 README.md(支持的搜索引擎列表)
- 构建并测试扩展包
- 创建 Git tag: v1.8.6
- 推送到 GitHub 触发自动发布
需求质量评分
最终评分: 95/100 ✅
| 评估维度 | 得分 | 详细说明 |
|---|---|---|
| 功能清晰度 | 28/30 | ✅ 用户交互流程完整明确 ✅ 成功标准清晰定义 ⚠️ DOM 选择器需要实际验证 |
| 技术特定性 | 23/25 | ✅ 集成点明确(复用现有架构) ✅ 技术约束清晰 ⚠️ 选择器验证后可达满分 |
| 实现完整性 | 24/25 | ✅ 边缘情况全面覆盖 ✅ 错误处理策略明确 ✅ 语法适配要求清晰 |
| 业务上下文 | 20/20 | ✅ 用户价值明确 ✅ 优先级清晰 ✅ 发布计划完整 |
评分说明
- 95 分已达到高质量标准 (目标: ≥90 分)
- 扣除 5 分原因: DOM 选择器需要实际页面验证
- 验证后可达满分: 选择器确认后更新文档
实施准备
已准备就绪
- ✅ 需求规格已完整定义
- ✅ 技术方案已明确(复用现有架构)
- ✅ 集成点已识别(4 个文件需修改)
- ✅ 测试策略已确定(手动测试)
- ✅ 发布计划已制定(1.8.6)
待执行任务
- DOM 选择器验证: 在实际页面验证选择器准确性
- 代码实施: 修改 4 个核心文件
- 手动测试: 执行完整测试清单
- 版本发布: 更新版本号并发布
附录:参考信息
现有实现参考
- Baidu 悬浮按钮:
src/content/FloatingPanelManager.ts - 悬浮图标:
src/content/components/TriggerIcon.ts - 消息桥接:
src/content/components/MessageBridge.ts - Yandex 适配器:
src/services/adapters/yandex.ts - DuckDuckGo 适配器:
src/services/adapters/duckduckgo.ts
关键代码模式
// 搜索引擎检测模式
function detectSearchEngine(hostname: string): string | null {
if (hostname.includes('yandex.com')) return 'yandex';
if (hostname.includes('duckduckgo.com')) return 'duckduckgo';
return null;
}
// 悬浮按钮初始化模式
async initialize(): Promise<void> {
this.config = getCurrentEngineConfig();
this.engineKey = detectSearchEngine(window.location.hostname);
if (!this.config || !this.engineKey) return;
await this.injectTriggerIcon();
}
批准状态
需求确认完成: ✅ 质量得分: 95/100 等待用户批准: 🔄
下一步: 等待用户确认后进入实施阶段(Phase 2)