commit 8ffb8a941d5be582b99af81850298e4ac56cd969 Author: 李岩岩 Date: Mon Feb 9 15:52:45 2026 +0800 feat(M1.1): 项目初始化 (v0.0.1) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89e1e8a --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Dependencies +node_modules/ +.pnpm-store/ + +# Build output +dist/ +dist-ssr/ +*.local + +# IDE +.vscode/* +!.vscode/extensions.json +.idea/ +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# OS +.DS_Store +Thumbs.db + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Testing +coverage/ + +# Environment +.env +.env.local +.env.*.local + +# Chrome Extension +*.zip +*.crx +*.pem diff --git a/docs/AGENTS.md b/docs/AGENTS.md new file mode 100644 index 0000000..45f51ed --- /dev/null +++ b/docs/AGENTS.md @@ -0,0 +1,319 @@ +# 沙拉查词项目规范 + +> 架构原则、代码风格、通信协议、安全规范 + +--- + +## 1. 架构原则 + +### 模块职责 + +| 模块 | 职责 | 禁止行为 | +|------|------|----------| +| **Background** | 网络请求、数据持久化、右键菜单 | 操作DOM | +| **Content Script** | 读取页面文本、注入UI、用户交互 | 直接跨域请求 | +| **Popup** | 独立查词、快速设置、历史记录 | 访问页面DOM | +| **Options** | 配置管理、生词本、词典账号 | 操作页面内容 | +| **Shared** | 工具函数、常量、基类 | 依赖特定模块 | + +### 通信规则 +``` +Content ↔ Background: chrome.runtime.sendMessage +Popup ↔ Background: chrome.runtime.sendMessage +Options → Background: chrome.runtime.sendMessage +``` + +--- + +## 2. 代码风格 + +### 命名规范 + +| 类型 | 规范 | 示例 | +|------|------|------| +| 文件 | 小写+连字符 | `salad-icon.js` | +| 类 | PascalCase | `DictionaryBase` | +| 函数 | camelCase+动词开头 | `getSelectionCoords()` | +| 常量 | UPPER_SNAKE_CASE | `DEFAULT_TIMEOUT` | +| 私有 | 下划线前缀 | `_handleMessage()` | +| 消息类型 | 大写+点分隔 | `DICT.SEARCH` | + +### JavaScript 规范 + +**必须使用**: +- `const` / `let`,禁止 `var` +- 箭头函数作为回调 +- 模板字符串 +- 解构赋值 +- 可选链 `?.` + +**禁止**: +- `eval()`, `new Function()` +- `innerHTML` 插入不可信内容 +- 同步的 `chrome.storage` 调用 + +**异步规范**: +```javascript +// ✅ async/await +async function searchWord(word) { + try { + const result = await dict.search(word); + return result; + } catch (error) { + console.error('Search failed:', error); + throw error; + } +} +``` + +### CSS 规范 + +**Shadow DOM 隔离**: +```javascript +const shadow = element.attachShadow({ mode: 'open' }); +shadow.innerHTML = ` + +
...
+`; +``` + +**CSS 变量**: +```css +:root { + --salad-primary: #4CAF50; + --salad-bg: #ffffff; + --salad-text: #333333; +} +[data-theme="dark"] { + --salad-bg: #1a1a1a; + --salad-text: #e0e0e0; +} +``` + +--- + +## 3. 通信协议 + +### 消息格式 +```javascript +// 请求 +{ + type: 'NAMESPACE.ACTION', + payload: { }, + meta: { timestamp, requestId } +} + +// 响应 +{ + type: 'NAMESPACE.ACTION_RESPONSE', + payload: { }, + error: null, + meta: { requestId } +} +``` + +### 标准消息类型 +```javascript +DICT.SEARCH / DICT.SEARCH_RESPONSE +CONFIG.GET / CONFIG.SET / CONFIG.CHANGED +WORD.ADD_FAVORITE / WORD.REMOVE_FAVORITE +CLIPBOARD.READ / CLIPBOARD.WRITE +HTTP.GET / HTTP.POST +``` + +### 通信封装 +```javascript +// shared/messaging.js +class MessageClient { + async send(type, payload, timeout = 5000) { + return new Promise((resolve, reject) => { + // 实现:发送消息,监听响应,超时处理 + }); + } +} +export const messaging = new MessageClient(); +``` + +--- + +## 4. 词典开发规范 + +### 基类定义 +```javascript +export class DictionaryBase { + constructor(config = {}) { + this.name = config.name || 'Unknown'; + this.icon = config.icon || ''; + this.languages = config.languages || ['en', 'zh']; + } + + async search(word) { + throw new Error('search() must be implemented'); + } + + supports(lang) { + return this.languages.includes(lang); + } +} +``` + +### 返回格式 +```javascript +{ + word: 'hello', + phonetic: '/həˈləʊ/', + meanings: [ + { partOfSpeech: 'int.', definitions: ['你好', '喂'] } + ], + examples: [ + { sentence: 'Hello, world!', translation: '你好,世界!' } + ], + url: 'https://...' +} +``` + +### 实现模板 +```javascript +export class XxxDictionary extends DictionaryBase { + constructor(config = {}) { + super({ name: '词典名', icon: 'icon.png', languages: ['en', 'zh'], ...config }); + } + + async search(word) { + if (!word?.trim()) throw new Error('Word is empty'); + + const html = await messaging.send('HTTP.GET', { + url: `https://api.example.com?q=${encodeURIComponent(word)}` + }); + + return this.parse(html, word); + } + + parse(html, word) { + const doc = new DOMParser().parseFromString(html, 'text/html'); + return { + word, + phonetic: this.extractPhonetic(doc), + meanings: this.extractMeanings(doc), + examples: this.extractExamples(doc), + url: '' + }; + } +} +``` + +--- + +## 5. UI 组件规范 + +### 组件基类 +```javascript +export class ComponentBase extends HTMLElement { + constructor() { + super(); + this.shadow = this.attachShadow({ mode: 'open' }); + this._isVisible = false; + } + + render() { + throw new Error('render() must be implemented'); + } + + show(x, y) { + this._isVisible = true; + this.style.display = 'block'; + this.style.left = `${x}px`; + this.style.top = `${y}px`; + } + + hide() { + this._isVisible = false; + this.style.display = 'none'; + } + + destroy() { + this.hide(); + this.remove(); + } +} +``` + +--- + +## 6. 存储规范 + +### 存储分层 +```javascript +chrome.storage.local // 配置、生词本 +chrome.storage.session // 临时数据 +IndexedDB // 大数据量 +Memory // 运行时缓存 +``` + +### 配置结构 +```javascript +const DEFAULT_CONFIG = { + version: '7.20.0', + general: { + enableSelection: true, + enableAnimation: true, + darkMode: false, + language: 'zh_CN' + }, + searchMode: { + triggerMode: 'icon', // icon/direct/double/key + iconHoverSearch: false, + shortcutKeys: [] + }, + dictionaries: [ + { id: 'bing', enabled: true, order: 0 } + ] +}; +``` + +--- + +## 7. 安全规范 + +### XSS 防护 +```javascript +// ✅ textContent +element.textContent = userInput; + +// ❌ innerHTML 插入不可信内容 +element.innerHTML = userInput; + +// ✅ 必须使用时转义 +function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} +``` + +### CSP +```json +{ + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" + } +} +``` + +--- + +## 8. 版本号规范 + +遵循 SemVer,但 **PATCH 与验收点关联**: + +``` +MAJOR.MINOR.PATCH +│ │ └─ 每个任务完成 +1 +│ └─ 模块完成进入下一模块 +1 +└─ 正式发布 = 1 +``` + +详见 [README.md](./README.md) 版本规则部分和 [VERSION.md](./VERSION.md) diff --git a/docs/M1.md b/docs/M1.md new file mode 100644 index 0000000..6851968 --- /dev/null +++ b/docs/M1.md @@ -0,0 +1,62 @@ +# M1 基础架构模块 (v0.0.1-0.0.5) + +## 模块概述 +- **版本范围**: 0.0.1 ~ 0.0.5 +- **任务数**: 5 +- **目标**: 搭建浏览器扩展插件的基础框架和开发环境 + +## 关键产出 +- 完整的项目目录结构(src/ 及其子目录) +- Manifest V3 配置文件 +- Vite + @crxjs 构建工具链 +- 模块间通信工具类(messaging.js) +- 支持 HMR 的完整开发流程 + +## 任务列表 + +### M1.1 项目初始化 [目标版本: 0.0.1] +**任务**: 创建项目目录结构 +**验收标准**: +- [ ] 存在 `src/` 目录,包含 `background/`, `content/`, `popup/`, `options/`, `shared/` 子目录 +- [ ] 存在 `package.json`,已初始化 npm 项目 +- [ ] 存在 `.gitignore`,排除 node_modules 和 dist + +### M1.2 Manifest V3 配置 [目标版本: 0.0.2] +**任务**: 编写 manifest.json +**验收标准**: +- [ ] manifest.json 位于项目根目录 +- [ ] 声明 `manifest_version: 3` +- [ ] 声明 `action` (popup) 入口 +- [ ] 声明 `background` (service_worker) 入口 +- [ ] 声明 `content_scripts` 匹配所有 URL (``) +- [ ] 声明必要权限:`storage`, `contextMenus`, `clipboardWrite` + +### M1.3 构建工具配置 [目标版本: 0.0.3] +**任务**: 配置 Vite + @crxjs/vite-plugin +**验收标准**: +- [ ] 运行 `npm run dev` 能启动开发服务器 +- [ ] 运行 `npm run build` 能生成 `dist/` 目录 +- [ ] dist 目录包含所有必要文件,可直接加载到 Chrome + +### M1.4 模块间通信工具 [目标版本: 0.0.4] +**任务**: 创建通信工具类 +**验收标准**: +- [ ] `src/shared/messaging.js` 存在 +- [ ] 封装 `sendToBackground()` 方法,content 可向 background 发消息 +- [ ] 封装 `sendToContent()` 方法,background 可向 content 发消息 +- [ ] 提供简单的 ping/pong 测试,验证通信链路通畅 + +### M1.5 开发环境验证 [目标版本: 0.0.5] +**任务**: 验证完整开发流程 +**验收标准**: +- [ ] Chrome 扩展管理页能加载 dist 目录 +- [ ] 修改代码后,扩展自动刷新(HMR) +- [ ] Console 无报错,各模块控制台能打印日志 + +## 依赖 +- **前置模块**: 无 +- **后置模块**: M2 划词核心模块 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M10.md b/docs/M10.md new file mode 100644 index 0000000..553deda --- /dev/null +++ b/docs/M10.md @@ -0,0 +1,74 @@ +# M10 高级功能模块 (v0.9.1-0.9.8) + +## 模块概述 +- **版本范围**: 0.9.1 ~ 0.9.8 +- **任务数**: 8 +- **目标**: 实现剪贴板操作、PDF支持和独立窗口等高级功能 + +## 关键产出 +- 权限管理页面 +- 剪贴板读取/写入权限及功能 +- 剪贴板快速查词 +- 复制原文/译文功能 +- PDF 划词支持 +- 独立窗口完善 + +## 任务列表 + +### M10.1 权限管理页面 [目标版本: 0.9.1] +**任务**: 权限说明和开关 +**验收标准**: +- [ ] 设置页"权限管理"菜单 +- [ ] 列出所需权限及用途说明 + +### M10.2 读取剪贴板权限 [目标版本: 0.9.2] +**任务**: 申请剪贴板读取权限 +**验收标准**: +- [ ] "读取剪贴板"开关 +- [ ] 开启时申请 `clipboardRead` 权限 +- [ ] 说明用途:快捷查词时读取剪贴板 + +### M10.3 剪贴板快速查词 [目标版本: 0.9.3] +**任务**: 打开Popup时自动查剪贴板内容 +**验收标准**: +- [ ] 开启权限后,打开Popup自动读取剪贴板 +- [ ] 如果剪贴板是单词,自动查询显示结果 + +### M10.4 写入剪贴板权限 [目标版本: 0.9.4] +**任务**: 申请剪贴板写入权限 +**验收标准**: +- [ ] "写入剪贴板"开关 +- [ ] 开启时申请 `clipboardWrite` 权限 + +### M10.5 复制原文功能 [目标版本: 0.9.5] +**任务**: 复制单词到剪贴板 +**验收标准**: +- [ ] 结果面板有"复制"按钮 +- [ ] 点击复制单词原文 + +### M10.6 复制译文功能 [目标版本: 0.9.6] +**任务**: 复制释义到剪贴板 +**验收标准**: +- [ ] 可复制单个释义,或全部释义 +- [ ] 复制后显示"已复制"提示 + +### M10.7 PDF支持 [目标版本: 0.9.7] +**任务**: 在PDF中启用划词 +**验收标准**: +- [ ] 在浏览器打开PDF文件时,划词功能可用 +- [ ] 可能需要适配 PDF.js 的文本层 + +### M10.8 独立窗口完善 [目标版本: 0.9.8] +**任务**: 独立查词窗口功能完整 +**验收标准**: +- [ ] 独立窗口有完整的搜索、历史、收藏功能 +- [ ] 窗口可置顶(always on top,如浏览器支持) +- [ ] 支持快捷键呼出(如 Alt+Shift+S) + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块, M5 设置系统模块 +- **后置模块**: 无 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M11.md b/docs/M11.md new file mode 100644 index 0000000..adef1e6 --- /dev/null +++ b/docs/M11.md @@ -0,0 +1,90 @@ +# M11 优化发布模块 (v0.10.1-1.0.0) + +## 模块概述 +- **版本范围**: 0.10.1 ~ 1.0.0 +- **任务数**: 10 +- **目标**: 性能优化、国际化、文档编写和发布准备 + +## 关键产出 +- 请求去重和取消机制 +- 虚拟滚动性能优化 +- 错误日志系统 +- 国际化(i18n)框架和英文翻译 +- 用户使用文档和开发文档 +- 生产环境打包配置 +- Chrome 商店发布素材 + +## 任务列表 + +### M11.1 请求去重 [目标版本: 0.10.1] +**任务**: 避免重复查询 +**验收标准**: +- [ ] 连续查询同一单词,使用缓存结果 +- [ ] 缓存有效期 5 分钟 + +### M11.2 请求取消 [目标版本: 0.10.2] +**任务**: 快速切换时取消旧请求 +**验收标准**: +- [ ] 使用 AbortController 取消未完成请求 +- [ ] 连续划词不同单词,旧查询不显示结果 + +### M11.3 虚拟滚动 [目标版本: 0.10.3] +**任务**: 生词本大量数据优化 +**验收标准**: +- [ ] 生词本超过100条时,使用虚拟滚动 +- [ ] 滚动流畅,不卡顿 + +### M11.4 错误日志 [目标版本: 0.10.4] +**任务**: 记录错误信息 +**验收标准**: +- [ ] 错误信息保存到 storage +- [ ] 设置页可查看最近错误日志 +- [ ] 提供"导出日志"功能 + +### M11.5 国际化(i18n)框架 [目标版本: 0.10.5] +**任务**: 多语言支持 +**验收标准**: +- [ ] `src/_locales/` 目录,含 zh_CN、en +- [ ] 所有界面文字使用 i18n 方式 +- [ ] 可切换界面语言 + +### M11.6 英文翻译 [目标版本: 0.10.6] +**任务**: 提供英文界面 +**验收标准**: +- [ ] 所有菜单、按钮有英文翻译 +- [ ] 设置页选择 English 后全部显示英文 + +### M11.7 使用文档 [目标版本: 0.10.7] +**任务**: 编写用户文档 +**验收标准**: +- [ ] README.md 说明安装使用方法 +- [ ] 功能介绍截图 + +### M11.8 开发文档 [目标版本: 0.10.8] +**任务**: 编写开发文档 +**验收标准**: +- [ ] 项目结构说明 +- [ ] 如何添加新词典的指南 +- [ ] 贡献指南 + +### M11.9 打包配置 [目标版本: 0.10.9] +**任务**: 生产环境打包 +**验收标准**: +- [ ] `npm run build:prod` 生成生产包 +- [ ] 代码压缩、去除 sourcemap +- [ ] 生成 zip 文件供上传 + +### M11.10 图标和素材 [目标版本: 1.0.0] +**任务**: 准备发布素材 +**验收标准**: +- [ ] 图标尺寸:16x16, 32x32, 48x48, 128x128 +- [ ] 截图:展示划词、Popup、设置页 +- [ ] 宣传图(Chrome商店用) + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块 +- **后置模块**: 无 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M2.md b/docs/M2.md new file mode 100644 index 0000000..fdd2e1a --- /dev/null +++ b/docs/M2.md @@ -0,0 +1,95 @@ +# M2 划词核心模块 (v0.1.1-0.1.9) + +## 模块概述 +- **版本范围**: 0.1.1 ~ 0.1.9 +- **任务数**: 9 +- **目标**: 实现网页文本选择检测和沙拉图标/面板交互功能 + +## 关键产出 +- 文本选择检测系统(selection.js) +- 沙拉图标组件(Shadow DOM 封装) +- 词典结果面板组件(DictPanel.js) +- 智能位置计算和视口适配 +- Popup 中的划词总开关 + +## 任务列表 + +### M2.1 文本选择检测 [目标版本: 0.1.1] +**任务**: 监听网页文本选择事件 +**验收标准**: +- [ ] `src/content/selection.js` 存在 +- [ ] 监听 `mouseup` 事件 +- [ ] 当选中文本长度 > 0 时,打印选中文本到控制台 +- [ ] 在任意网页划词,Console 能看到选中的文本 + +### M2.2 获取选中文本坐标 [目标版本: 0.1.2] +**任务**: 计算选中文本的位置信息 +**验收标准**: +- [ ] 函数 `getSelectionCoords()` 返回 `{x, y, width, height}` +- [ ] 支持单行文本选择 +- [ ] 支持多行文本选择(返回首行或整个选区的矩形) +- [ ] 坐标值正确(相对于视口) + +### M2.3 沙拉图标组件(基础) [目标版本: 0.1.3] +**任务**: 创建浮动图标元素 +**验收标准**: +- [ ] `src/content/components/SaladIcon.js` 存在 +- [ ] 图标为 24x24px 的 div,背景色为绿色(先不用真实Logo) +- [ ] 使用 Shadow DOM 封装,样式不泄露到页面 +- [ ] 图标 `position: fixed`,可定位到任意坐标 + +### M2.4 图标定位显示 [目标版本: 0.1.4] +**任务**: 划词后图标出现在选中文本附近 +**验收标准**: +- [ ] 划词后,图标显示在选中文本右上角(x + width, y) +- [ ] 图标不随页面滚动而偏移(使用 fixed 定位) +- [ ] 再次划词时,先隐藏旧图标,再显示新图标 +- [ ] 点击页面空白处,图标消失 + +### M2.5 图标点击事件 [目标版本: 0.1.5] +**任务**: 点击图标触发回调 +**验收标准**: +- [ ] 点击图标时,打印 "icon clicked" 到控制台 +- [ ] 回调函数可配置(通过参数传入) +- [ ] 点击后图标不消失(后续再处理) + +### M2.6 基础面板组件 [目标版本: 0.1.6] +**任务**: 创建词典结果展示面板 +**验收标准**: +- [ ] `src/content/components/DictPanel.js` 存在 +- [ ] 面板尺寸 400x300px,白色背景,带阴影 +- [ ] 使用 Shadow DOM 封装 +- [ ] 面板内显示标题 "词典结果" +- [ ] 提供 `show(x, y)` 和 `hide()` 方法 + +### M2.7 面板位置计算 [目标版本: 0.1.7] +**任务**: 面板智能定位,不超出视口 +**验收标准**: +- [ ] 面板默认显示在图标右下方 +- [ ] 如果右侧超出视口,显示在左侧 +- [ ] 如果下方超出视口,显示在上方 +- [ ] 面板边界与视口保留 10px 边距 + +### M2.8 图标-面板联动 [目标版本: 0.1.8] +**任务**: 点击图标显示面板 +**验收标准**: +- [ ] 点击图标,面板显示在图标附近 +- [ ] 面板显示时,图标保持可见 +- [ ] 点击面板外部区域,面板关闭 +- [ ] 按 ESC 键,面板关闭 + +### M2.9 图标显示开关 [目标版本: 0.1.9] +**任务**: Popup 中添加总开关 +**验收标准**: +- [ ] Popup 中有一个 Toggle 开关,标签"启用划词" +- [ ] 开关状态保存到 `chrome.storage.local` +- [ ] 关闭开关后,网页划词不再显示图标 +- [ ] 打开开关后,恢复划词显示图标 + +## 依赖 +- **前置模块**: M1 基础架构模块 +- **后置模块**: M3 词典系统模块, M5 设置系统模块 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M3.md b/docs/M3.md new file mode 100644 index 0000000..f3973c3 --- /dev/null +++ b/docs/M3.md @@ -0,0 +1,107 @@ +# M3 词典系统模块 (v0.2.1-0.2.11) + +## 模块概述 +- **版本范围**: 0.2.1 ~ 0.2.11 +- **任务数**: 11 +- **目标**: 构建词典接口体系,支持多词典源查询和结果展示 + +## 关键产出 +- 词典接口基类设计(DictionaryBase) +- 词典管理器(支持多词典注册和查询) +- 必应词典和有道词典实现 +- 后台查询接口(Background Service Worker) +- 结果展示组件(支持折叠/展开) + +## 任务列表 + +### M3.1 词典接口基类设计 [目标版本: 0.2.1] +**任务**: 定义词典抽象接口 +**验收标准**: +- [ ] `src/shared/dictionary/base.js` 存在 +- [ ] 定义 `DictionaryBase` 类 +- [ ] 要求子类实现 `search(word)` 方法 +- [ ] 定义统一的返回格式:`{word, phonetic, meanings[], examples[]}` + +### M3.2 词典管理器 [目标版本: 0.2.2] +**任务**: 管理多个词典实例 +**验收标准**: +- [ ] `src/shared/dictionary/manager.js` 存在 +- [ ] 提供 `register(name, dictionaryInstance)` 注册词典 +- [ ] 提供 `search(word, dictNames[])` 查询指定词典 +- [ ] 提供 `getAll()` 获取所有已注册词典 + +### M3.3 必应词典实现(Mock版) [目标版本: 0.2.3] +**任务**: 先实现假数据版本 +**验收标准**: +- [ ] `src/shared/dictionary/bing.js` 存在 +- [ ] 继承 `DictionaryBase` +- [ ] `search(word)` 返回模拟数据(不调用真实API) +- [ ] 模拟数据包含:单词、音标、词性、中文释义、例句 + +### M3.4 后台查询接口 [目标版本: 0.2.4] +**任务**: background 处理词典查询请求 +**验收标准**: +- [ ] background 监听 `DICT_SEARCH` 消息 +- [ ] 调用词典管理器执行查询 +- [ ] 返回查询结果给 content script +- [ ] Console 可看到查询结果 + +### M3.5 结果展示组件(静态) [目标版本: 0.2.5] +**任务**: 面板中显示词典结果 +**验收标准**: +- [ ] 面板内显示单词标题(大字) +- [ ] 显示音标(如果有) +- [ ] 显示词性和中文释义列表 +- [ ] 显示1-2个例句(英文+中文翻译) + +### M3.6 点击图标查词(Mock数据) [目标版本: 0.2.6] +**任务**: 打通完整流程 +**验收标准**: +- [ ] 网页划词,点击图标 +- [ ] 面板显示该单词的 Mock 查询结果 +- [ ] 结果显示格式正确,可读 + +### M3.7 必应词典真实API [目标版本: 0.2.7] +**任务**: 调用必应词典接口 +**验收标准**: +- [ ] 使用 fetch 请求必应词典网页 +- [ ] 解析 HTML 提取释义数据 +- [ ] 错误时返回友好提示(如"查询失败,请检查网络") +- [ ] 替换 Mock 数据,显示真实结果 + +### M3.8 加载状态显示 [目标版本: 0.2.8] +**任务**: 查询时显示 loading +**验收标准**: +- [ ] 点击图标后,面板先显示 loading 动画 +- [ ] 查询完成后,loading 消失,显示结果 +- [ ] 查询超时(5秒)显示"查询超时" + +### M3.9 有道词典实现 [目标版本: 0.2.9] +**任务**: 添加第二个词典源 +**验收标准**: +- [ ] `src/shared/dictionary/youdao.js` 存在 +- [ ] 实现 `search(word)` 调用有道API或网页 +- [ ] 注册到词典管理器 +- [ ] 面板中可同时显示必应和有道结果 + +### M3.10 结果折叠/展开 [目标版本: 0.2.10] +**任务**: 词典结果可折叠 +**验收标准**: +- [ ] 每个词典结果区域有标题栏(词典名+展开/折叠按钮) +- [ ] 点击标题栏可折叠/展开该词典结果 +- [ ] 折叠状态用图标表示(▼/▶) + +### M3.11 词典图标标识 [目标版本: 0.2.11] +**任务**: 每个词典显示对应Logo +**验收标准**: +- [ ] 必应结果前有必应图标(或颜色标识) +- [ ] 有道结果前有道图标 +- [ ] 图标使用小尺寸(16x16px) + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块 +- **后置模块**: M4 Popup查词模块, M6 触发方式模块, M9 API账号模块 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M4.md b/docs/M4.md new file mode 100644 index 0000000..6afc5df --- /dev/null +++ b/docs/M4.md @@ -0,0 +1,82 @@ +# M4 Popup查词模块 (v0.3.1-0.3.8) + +## 模块概述 +- **版本范围**: 0.3.1 ~ 0.3.8 +- **任务数**: 8 +- **目标**: 构建独立弹窗界面,支持搜索、历史记录和独立窗口 + +## 关键产出 +- Popup 页面框架(HTML/JS/CSS) +- 搜索功能和自动补全建议 +- 查询历史记录系统 +- 前进后退导航功能 +- 独立窗口支持 + +## 任务列表 + +### M4.1 Popup基础界面 [目标版本: 0.3.1] +**任务**: 创建 Popup 页面框架 +**验收标准**: +- [ ] `src/popup/` 目录存在,含 HTML/JS/CSS +- [ ] Popup 宽度 400px,高度自适应(最小400px) +- [ ] 顶部有搜索输入框 +- [ ] 中间为结果展示区 +- [ ] 底部有"启用划词"开关 + +### M4.2 Popup搜索功能 [目标版本: 0.3.2] +**任务**: 输入单词查询 +**验收标准**: +- [ ] 在输入框输入单词,按 Enter 触发查询 +- [ ] 查询结果显示在下方(复用 content 的结果组件) +- [ ] 支持查询多个词典 + +### M4.3 搜索建议(Autocomplete) [目标版本: 0.3.3] +**任务**: 输入时显示单词建议 +**验收标准**: +- [ ] 输入时,下拉显示匹配单词列表 +- [ ] 使用简单的内置词库(100个常用词) +- [ ] 点击建议项,自动填入并查询 +- [ ] 键盘上下键可选择建议项 + +### M4.4 查询历史记录 [目标版本: 0.3.4] +**任务**: 保存查询历史 +**验收标准**: +- [ ] 每次查询保存到 `chrome.storage.local` +- [ ] 最多保存 50 条历史 +- [ ] Popup 顶部有历史记录按钮 + +### M4.5 历史记录展示 [目标版本: 0.3.5] +**任务**: 查看和选择历史 +**验收标准**: +- [ ] 点击历史按钮,显示历史单词列表 +- [ ] 点击历史单词,直接查询该单词 +- [ ] 历史列表可清空 + +### M4.6 前进后退导航 [目标版本: 0.3.6] +**任务**: 像浏览器一样前进后退 +**验收标准**: +- [ ] Popup 顶部有前进、后退按钮 +- [ ] 查询新单词后,可后退到上一个结果 +- [ ] 支持键盘快捷键 Alt+←/→ + +### M4.7 收藏按钮(UI占位) [目标版本: 0.3.7] +**任务**: 添加心形收藏按钮 +**验收标准**: +- [ ] 结果区域右上角有心形图标 +- [ ] 点击切换空心/实心状态 +- [ ] 暂不需要实际存储(仅UI) + +### M4.8 独立窗口打开 [目标版本: 0.3.8] +**任务**: Popup 可打开独立窗口 +**验收标准**: +- [ ] Popup 有"打开独立窗口"按钮 +- [ ] 点击后打开新窗口,URL 为 `chrome-extension://.../standalone.html` +- [ ] 独立窗口尺寸 600x500px,可调整大小 + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块, M3 词典系统模块 +- **后置模块**: M8 生词本模块 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M5.md b/docs/M5.md new file mode 100644 index 0000000..2dd9664 --- /dev/null +++ b/docs/M5.md @@ -0,0 +1,134 @@ +# M5 设置系统模块 (v0.4.1-0.4.16) + +## 模块概述 +- **版本范围**: 0.4.1 ~ 0.4.16 +- **任务数**: 16 +- **目标**: 构建完整的设置页面和配置管理系统 + +## 关键产出 +- Options 设置页面框架 +- 配置存储工具(config.js) +- 基本选项(开关、动画、主题、语言) +- 查词习惯设置 +- 词典管理(添加、排序、删除) + +## 任务列表 + +### M5.1 设置页面框架 [目标版本: 0.4.1] +**任务**: 创建 Options 页面 +**验收标准**: +- [ ] `src/options/` 目录存在 +- [ ] 点击"扩展选项"能打开设置页 +- [ ] 左侧为导航菜单,右侧为内容区 +- [ ] 菜单项:基本选项、查词习惯、词典设置、词典账号、右键菜单、权限管理 + +### M5.2 配置存储工具 [目标版本: 0.4.2] +**任务**: 封装配置读写 +**验收标准**: +- [ ] `src/shared/config.js` 存在 +- [ ] `getConfig(key)` 读取配置,支持默认值 +- [ ] `setConfig(key, value)` 保存配置 +- [ ] 配置变更时触发事件通知 + +### M5.3 基本选项-划词翻译开关 [目标版本: 0.4.3] +**任务**: 总开关设置 +**验收标准**: +- [ ] 设置页"基本选项"中有"启用划词翻译"开关 +- [ ] 开关状态与 Popup 中的开关同步 +- [ ] 关闭后,所有页面划词不再触发 + +### M5.4 基本选项-动画开关 [目标版本: 0.4.4] +**任务**: 控制动画效果 +**验收标准**: +- [ ] "开启动画过渡"开关 +- [ ] 开启时,图标/面板有淡入淡出动画 +- [ ] 关闭时,瞬间显示/隐藏 + +### M5.5 基本选项-后台运行 [目标版本: 0.4.5] +**任务**: 后台保持运行 +**验收标准**: +- [ ] "后台保持运行"开关 +- [ ] 开启后,浏览器关闭后扩展仍响应快捷键 +- [ ] (V3限制,可能需要 keep-alive 技巧) + +### M5.6 基本选项-黑暗模式 [目标版本: 0.4.6] +**任务**: 主题切换 +**验收标准**: +- [ ] "黑暗模式"开关 +- [ ] 开启后,面板、Popup、设置页变为深色主题 +- [ ] 颜色对比度正常,可读 + +### M5.7 基本选项-界面语言 [目标版本: 0.4.7] +**任务**: 多语言界面 +**验收标准**: +- [ ] "界面语言"下拉选择(简体中文、English) +- [ ] 切换后,设置页菜单文字立即变化 +- [ ] (其他页面后续实现) + +### M5.8 查词习惯-输入框排除 [目标版本: 0.4.8] +**任务**: 不在输入框划词 +**验收标准**: +- [ ] "不在输入框划词"开关 +- [ ] 开启后,在 input/textarea/contenteditable 中选词不触发图标 + +### M5.9 查词习惯-触摸模式 [目标版本: 0.4.9] +**任务**: 适配触摸设备 +**验收标准**: +- [ ] "触摸模式"开关 +- [ ] 开启后,支持长按选词触发 +- [ ] 支持触摸事件(touchstart/touchend) + +### M5.10 查词习惯-划词语言 [目标版本: 0.4.10] +**任务**: 选择划词语言 +**验收标准**: +- [ ] 复选框组:中文、英文、日文、韩文、法文、西班牙文、德文 +- [ ] 只选中文时,选中英文文本不触发 +- [ ] 选择"其它字符"时,匹配所有语言 + +### M5.11 查词习惯-记忆折叠 [目标版本: 0.4.11] +**任务**: 记住词典折叠状态 +**验收标准**: +- [ ] "记忆折叠"开关 +- [ ] 开启后,用户折叠某个词典,下次查询默认折叠 + +### M5.12 查词习惯-双击间隔 [目标版本: 0.4.12] +**任务**: 调整双击灵敏度 +**验收标准**: +- [ ] "双击间隔"滑块,范围 0.1-2 秒 +- [ ] 数值实时显示 + +### M5.13 词典设置-已选词典列表 [目标版本: 0.4.13] +**任务**: 管理启用的词典 +**验收标准**: +- [ ] "词典设置"页显示已选词典列表 +- [ ] 每行显示:图标、词典名、支持语言、操作按钮 +- [ ] 当前有:必应词典、有道词典 + +### M5.14 词典设置-添加词典 [目标版本: 0.4.14] +**任务**: 添加新词典 +**验收标准**: +- [ ] "+ 添加"按钮 +- [ ] 点击显示可用词典列表 +- [ ] 选择后添加到已选列表 + +### M5.15 词典设置-排序 [目标版本: 0.4.15] +**任务**: 调整词典顺序 +**验收标准**: +- [ ] 每行有"上移"/"下移"按钮 +- [ ] 点击调整词典在列表中的位置 +- [ ] 查询结果按此顺序显示 + +### M5.16 词典设置-删除 [目标版本: 0.4.16] +**任务**: 移除词典 +**验收标准**: +- [ ] 每行有删除按钮(X) +- [ ] 点击确认后移除 +- [ ] 至少保留一个词典 + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块 +- **后置模块**: M7 右键菜单模块, M8 生词本模块, M10 高级功能模块 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M6.md b/docs/M6.md new file mode 100644 index 0000000..3ba94b1 --- /dev/null +++ b/docs/M6.md @@ -0,0 +1,74 @@ +# M6 触发方式模块 (v0.5.1-0.5.7) + +## 模块概述 +- **版本范围**: 0.5.1 ~ 0.5.7 +- **任务数**: 7 +- **目标**: 实现多种划词触发方式,适应不同用户习惯 + +## 关键产出 +- 普通划词显示图标模式 +- 图标悬停查词功能 +- 图标位置偏移设置 +- 直接搜索模式 +- 双击搜索模式 +- 快捷键搜索模式 +- 鼠标悬浮取词功能 + +## 任务列表 + +### M6.1 普通划词-显示图标 [目标版本: 0.5.1] +**任务**: 默认模式 +**验收标准**: +- [ ] "显示图标"选项(默认开启) +- [ ] 划词后在文本旁显示沙拉图标 +- [ ] 这是当前已实现的功能 + +### M6.2 普通划词-图标悬停查词 [目标版本: 0.5.2] +**任务**: 鼠标悬停图标触发 +**验收标准**: +- [ ] "图标悬停查词"选项 +- [ ] 开启后,鼠标悬停在图标上(无需点击)即显示面板 +- [ ] 悬停延迟 200ms,避免误触 + +### M6.3 图标位置偏移 [目标版本: 0.5.3] +**任务**: 调整图标位置 +**验收标准**: +- [ ] "图标水平偏移"滑块(-100px 到 100px) +- [ ] "图标垂直偏移"滑块(-100px 到 100px) +- [ ] 调整后在网页划词,图标位置相应偏移 + +### M6.4 直接搜索模式 [目标版本: 0.5.4] +**任务**: 划词直接显示面板 +**验收标准**: +- [ ] "直接搜索"选项 +- [ ] 开启后,划词立即显示面板(不显示图标) +- [ ] 与"显示图标"选项互斥 + +### M6.5 双击搜索模式 [目标版本: 0.5.5] +**任务**: 双击文本触发 +**验收标准**: +- [ ] "双击搜索"选项 +- [ ] 双击选中文本后,直接显示面板 +- [ ] 双击间隔使用 M5.12 的设置值 + +### M6.6 快捷键搜索模式 [目标版本: 0.5.6] +**任务**: 按住快捷键划词触发 +**验收标准**: +- [ ] 复选框:Ctrl、Alt、Shift、Meta +- [ ] 选中后,划词时只有按住对应键才显示图标/面板 +- [ ] 支持多键组合(如 Ctrl+Shift) + +### M6.7 鼠标悬浮取词(划词即查) [目标版本: 0.5.7] +**任务**: 鼠标悬停自动选词查询 +**验收标准**: +- [ ] "鼠标悬浮取词"开关 +- [ ] 开启后,鼠标悬停在单词上 500ms 自动查询 +- [ ] 需要检测光标下的单词(使用 caretPositionFromPoint) + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块, M3 词典系统模块, M5 设置系统模块 +- **后置模块**: 无 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M7.md b/docs/M7.md new file mode 100644 index 0000000..437e731 --- /dev/null +++ b/docs/M7.md @@ -0,0 +1,63 @@ +# M7 右键菜单模块 (v0.6.1-0.6.6) + +## 模块概述 +- **版本范围**: 0.6.1 ~ 0.6.6 +- **任务数**: 6 +- **目标**: 实现上下文菜单功能,支持快捷查词和自定义链接 + +## 关键产出 +- 右键上下文菜单注册 +- 沙拉查词子菜单功能 +- 网页翻译集成(彩云小译、谷歌翻译) +- 自定义右键菜单链接 +- 右键菜单排序和开关控制 + +## 任务列表 + +### M7.1 右键菜单注册 [目标版本: 0.6.1] +**任务**: 创建上下文菜单 +**验收标准**: +- [ ] background 中使用 `chrome.contextMenus.create` +- [ ] 选中文字时右键显示"沙拉查词"主菜单 +- [ ] 有图标显示 + +### M7.2 沙拉查词子菜单 [目标版本: 0.6.2] +**任务**: 点击执行查词 +**验收标准**: +- [ ] 子菜单项:"沙拉查词" +- [ ] 点击后在页面显示查词面板(像划词一样) + +### M7.3 网页翻译菜单 [目标版本: 0.6.3] +**任务**: 集成网页翻译 +**验收标准**: +- [ ] 子菜单项:"彩云小译网页翻译" +- [ ] 子菜单项:"谷歌翻译" +- [ ] 点击后打开对应翻译网站,自动填入当前页面URL + +### M7.4 自定义右键菜单 [目标版本: 0.6.4] +**任务**: 用户添加自定义链接 +**验收标准**: +- [ ] 设置页"右键菜单"中有列表 +- [ ] 可添加自定义链接(名称+URL) +- [ ] URL 支持 `{word}` 占位符(替换为选中文字) +- [ ] 右键菜单中显示自定义项 + +### M7.5 右键菜单排序 [目标版本: 0.6.5] +**任务**: 调整菜单顺序 +**验收标准**: +- [ ] 设置页可拖拽排序右键菜单项 +- [ ] 或提供上移/下移按钮 + +### M7.6 右键菜单开关 [目标版本: 0.6.6] +**任务**: 控制显示哪些菜单 +**验收标准**: +- [ ] 每个菜单项可勾选显示/隐藏 +- [ ] 隐藏后右键不再显示 + +## 依赖 +- **前置模块**: M1 基础架构模块, M5 设置系统模块 +- **后置模块**: 无 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M8.md b/docs/M8.md new file mode 100644 index 0000000..47323d8 --- /dev/null +++ b/docs/M8.md @@ -0,0 +1,88 @@ +# M8 生词本模块 (v0.7.1-0.7.10) + +## 模块概述 +- **版本范围**: 0.7.1 ~ 0.7.10 +- **任务数**: 10 +- **目标**: 构建完整的生词本系统,支持收藏、管理和导出 + +## 关键产出 +- 收藏功能实现(心形图标) +- IndexedDB 数据库封装 +- 生词本页面(列表展示、搜索、删除) +- 多格式导出(JSON、CSV、Anki) +- 生词导入功能 +- 上下文保存功能 + +## 任务列表 + +### M8.1 收藏功能实现 [目标版本: 0.7.1] +**任务**: 点击心形收藏单词 +**验收标准**: +- [ ] 点击面板/Popup中的心形图标,保存单词 +- [ ] 实心表示已收藏,空心表示未收藏 +- [ ] 再次点击取消收藏 + +### M8.2 生词本数据库 [目标版本: 0.7.2] +**任务**: 使用 IndexedDB 存储 +**验收标准**: +- [ ] `src/shared/database.js` 封装 IndexedDB +- [ ] 表结构:id, word, phonetic, translation, context, url, timestamp +- [ ] 提供 `add()`, `remove()`, `getAll()`, `search()` 方法 + +### M8.3 生词本页面 [目标版本: 0.7.3] +**任务**: 查看收藏的单词 +**验收标准**: +- [ ] 设置页新增"生词本"菜单 +- [ ] 以列表形式展示所有生词 +- [ ] 显示:单词、音标、释义、收藏时间 + +### M8.4 生词本搜索 [目标版本: 0.7.4] +**任务**: 搜索生词 +**验收标准**: +- [ ] 生词本页顶部有搜索框 +- [ ] 输入时实时过滤列表 + +### M8.5 生词本删除 [目标版本: 0.7.5] +**任务**: 移除生词 +**验收标准**: +- [ ] 每个生词项有删除按钮 +- [ ] 支持批量删除(复选框+删除选中) + +### M8.6 生词本导出(JSON) [目标版本: 0.7.6] +**任务**: 导出为 JSON 格式 +**验收标准**: +- [ ] "导出"按钮,选择 JSON 格式 +- [ ] 下载 .json 文件,包含所有生词数据 + +### M8.7 生词本导出(CSV) [目标版本: 0.7.7] +**任务**: 导出为 CSV 格式 +**验收标准**: +- [ ] 导出选项包含 CSV 格式 +- [ ] CSV 列:单词,音标,释义,例句,来源URL,时间 + +### M8.8 生词本导出(Anki) [目标版本: 0.7.8] +**任务**: 导出为 Anki 格式 +**验收标准**: +- [ ] 导出选项包含 Anki (.txt) +- [ ] 格式兼容 Anki 导入(制表符分隔) + +### M8.9 生词本导入 [目标版本: 0.7.9] +**任务**: 从文件导入 +**验收标准**: +- [ ] "导入"按钮,支持 JSON 格式 +- [ ] 导入后生词追加到现有生词本 + +### M8.10 收藏时添加上下文 [目标版本: 0.7.10] +**任务**: 保存单词出现的句子 +**验收标准**: +- [ ] 收藏时,自动提取单词所在句子(从页面文本中) +- [ ] 保存到生词本的 context 字段 +- [ ] 生词本列表中可展开查看上下文 + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块, M5 设置系统模块 +- **后置模块**: 无 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/M9.md b/docs/M9.md new file mode 100644 index 0000000..d3ec2ed --- /dev/null +++ b/docs/M9.md @@ -0,0 +1,68 @@ +# M9 API账号模块 (v0.8.1-0.8.7) + +## 模块概述 +- **版本范围**: 0.8.1 ~ 0.8.7 +- **任务数**: 7 +- **目标**: 支持第三方翻译 API 的账号配置和安全存储 + +## 关键产出 +- 词典账号配置页面 +- 百度翻译 API 配置 +- 彩云小译 API 配置 +- 搜狗翻译 API 配置 +- 腾讯翻译君 API 配置 +- 有道翻译 API 配置 +- API 密钥加密存储机制 + +## 任务列表 + +### M9.1 账号配置页面 [目标版本: 0.8.1] +**任务**: 词典账号设置界面 +**验收标准**: +- [ ] 设置页"词典账号"菜单 +- [ ] 说明文字:建议申请官方账号获得更稳定体验 + +### M9.2 百度翻译API配置 [目标版本: 0.8.2] +**任务**: 配置百度翻译密钥 +**验收标准**: +- [ ] 输入框:appid、key +- [ ] 链接到百度翻译开放平台 +- [ ] 配置后百度翻译使用用户密钥 + +### M9.3 彩云小译API配置 [目标版本: 0.8.3] +**任务**: 配置彩云小译 token +**验收标准**: +- [ ] 输入框:token +- [ ] 配置后彩云小译使用用户 token + +### M9.4 搜狗翻译API配置 [目标版本: 0.8.4] +**任务**: 配置搜狗翻译密钥 +**验收标准**: +- [ ] 输入框:pid、key +- [ ] 配置后搜狗翻译使用用户密钥 + +### M9.5 腾讯翻译君API配置 [目标版本: 0.8.5] +**任务**: 配置腾讯翻译密钥 +**验收标准**: +- [ ] 输入框:secretId、secretKey +- [ ] 配置后腾讯翻译使用用户密钥 + +### M9.6 有道翻译API配置 [目标版本: 0.8.6] +**任务**: 配置有道翻译密钥 +**验收标准**: +- [ ] 输入框:appKey、key +- [ ] 配置后有道翻译使用用户密钥 + +### M9.7 API密钥加密存储 [目标版本: 0.8.7] +**任务**: 安全存储密钥 +**验收标准**: +- [ ] 密钥不直接明文存储(使用简单异或加密) +- [ ] 或注明"密钥仅保存在本地浏览器中" + +## 依赖 +- **前置模块**: M1 基础架构模块, M2 划词核心模块, M3 词典系统模块, M5 设置系统模块 +- **后置模块**: 无 + +## 参考资料 +- [AGENTS.md](./AGENTS.md) - 规范文档 +- [QUICK_REF.md](./QUICK_REF.md) - 快速参考 diff --git a/docs/QUICK_REF.md b/docs/QUICK_REF.md new file mode 100644 index 0000000..fdb4c93 --- /dev/null +++ b/docs/QUICK_REF.md @@ -0,0 +1,217 @@ +# 快速参考 + +> 版本速查、命名规范、代码模板 + +--- + +## 版本速查 + +### 当前版本 +`0.0.1` → 下一目标 `0.0.2` ([M1.2](./M1.md)) + +### 模块版本范围 + +| 模块 | 范围 | 任务数 | +|------|------|--------| +| M1 | 0.0.1 ~ 0.0.5 | 5 | +| M2 | 0.1.1 ~ 0.1.9 | 9 | +| M3 | 0.2.1 ~ 0.2.11 | 11 | +| M4 | 0.3.1 ~ 0.3.8 | 8 | +| M5 | 0.4.1 ~ 0.4.16 | 16 | +| M6 | 0.5.1 ~ 0.5.7 | 7 | +| M7 | 0.6.1 ~ 0.6.6 | 6 | +| M8 | 0.7.1 ~ 0.7.10 | 10 | +| M9 | 0.8.1 ~ 0.8.7 | 7 | +| M10 | 0.9.1 ~ 0.9.8 | 8 | +| M11 | 0.10.1 ~ 1.0.0 | 10 | + +### 版本更新 +```bash +# M1.1 完成后 +版本: 0.0.0 → 0.0.1 +git commit -m "feat(M1.1): 项目初始化 (v0.0.1)" + +# M2.1 完成后 (进入M2) +版本: 0.0.5 → 0.1.1 +git commit -m "feat(M2.1): 文本选择检测 (v0.1.1)" +``` + +--- + +## 命名速查 + +| 类型 | 规范 | 示例 | +|------|------|------| +| 文件 | 小写+连字符 | `salad-icon.js` | +| 类 | PascalCase | `DictionaryBase` | +| 函数 | camelCase+动词 | `getSelectionCoords()` | +| 常量 | UPPER_SNAKE | `DEFAULT_TIMEOUT` | +| 私有 | _前缀 | `_cache`, `_handle()` | +| 消息 | 大写+点 | `DICT.SEARCH` | + +--- + +## 消息类型速查 + +```javascript +DICT.SEARCH / DICT.SEARCH_RESPONSE +CONFIG.GET / CONFIG.SET / CONFIG.CHANGED +WORD.ADD_FAVORITE / WORD.REMOVE_FAVORITE +CLIPBOARD.READ / CLIPBOARD.WRITE +HTTP.GET / HTTP.POST +``` + +--- + +## 代码模板 + +### package.json(0.0.0) +```json +{ + "name": "salad-dict", + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "dependencies": { + "vue": "^3.4.0", + "vue-router": "^4.2.0", + "pinia": "^2.1.0", + "localforage": "^1.10.0" + }, + "devDependencies": { + "@crxjs/vite-plugin": "^2.0.0", + "@vitejs/plugin-vue": "^5.0.0", + "vite": "^5.0.0" + } +} +``` + +### manifest.json(0.0.0) +```json +{ + "manifest_version": 3, + "name": "沙拉查词", + "version": "0.0.0", + "permissions": ["storage", "contextMenus", "clipboardWrite"], + "optional_permissions": ["clipboardRead"], + "host_permissions": [""], + "background": { + "service_worker": "src/background/index.js", + "type": "module" + }, + "content_scripts": [{ + "matches": [""], + "js": ["src/content/index.js"], + "run_at": "document_end" + }], + "action": { + "default_popup": "src/popup/index.html" + }, + "options_page": "src/options/index.html" +} +``` + +### 词典实现 +```javascript +import { DictionaryBase } from './base.js'; +import { messaging } from '../messaging.js'; + +export class XxxDictionary extends DictionaryBase { + constructor(config = {}) { + super({ name: '词典名', icon: 'icon.png', languages: ['en', 'zh'], ...config }); + } + + async search(word) { + if (!word?.trim()) throw new Error('Word is empty'); + const html = await messaging.send('HTTP.GET', { url: `...${encodeURIComponent(word)}` }); + return this.parse(html, word); + } + + parse(html, word) { + const doc = new DOMParser().parseFromString(html, 'text/html'); + return { + word, + phonetic: '', + meanings: [{ partOfSpeech: 'n.', definitions: ['释义'] }], + examples: [{ sentence: '例句', translation: '翻译' }], + url: '' + }; + } +} +``` + +### UI组件 +```javascript +export class XxxComponent extends HTMLElement { + constructor() { + super(); + this.shadow = this.attachShadow({ mode: 'open' }); + this.render(); + } + + render() { + this.shadow.innerHTML = ` + +
...
+ `; + } + + show(x, y) { + this.style.left = `${x}px`; + this.style.top = `${y}px`; + this.style.display = 'block'; + } + + hide() { + this.style.display = 'none'; + } +} +``` + +### 通信封装 +```javascript +class MessageClient { + async send(type, payload, timeout = 5000) { + const requestId = generateUUID(); + return new Promise((resolve, reject) => { + const timer = setTimeout(() => reject(new Error('Timeout')), timeout); + const handler = (response) => { + if (response.meta?.requestId !== requestId) return; + clearTimeout(timer); + chrome.runtime.onMessage.removeListener(handler); + response.error ? reject(new Error(response.error.message)) : resolve(response.payload); + }; + chrome.runtime.onMessage.addListener(handler); + chrome.runtime.sendMessage({ type, payload, meta: { requestId } }); + }); + } +} +export const messaging = new MessageClient(); +``` + +--- + +## 调试技巧 + +```javascript +// Content Script +console.log('[Content]', message); + +// Background (看 Service Worker console) +chrome.action.onClicked.addListener(() => { + console.log('[Background]', 'clicked'); +}); + +// 强制刷新扩展 +chrome.runtime.reload(); +``` + +**Chrome 扩展 DevTools**: +- `chrome://extensions/` → "service worker" (background) +- "inspect views" (popup) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..16e852c --- /dev/null +++ b/docs/README.md @@ -0,0 +1,131 @@ +# 沙拉查词开发文档总纲 + +> 项目概述、版本规则、模块索引 + +--- + +## 项目概述 + +- **项目名称**:沙拉查词 +- **类型**:Chrome Extension (Manifest V3) +- **核心功能**:划词翻译、多词典聚合查询 +- **目标浏览器**:Chrome 109+ + +**技术栈**: +- Chrome Extension Manifest V3 +- JavaScript ES2022+ +- Vue.js ^3.4.0 (Popup/Options) +- Vite ^5.0.0 +- Node.js >= 18.0.0 + +--- + +## 版本号规则 + +### 格式 +`MAJOR.MINOR.PATCH` + +| 位 | 含义 | 更新时机 | +|----|------|----------| +| MAJOR | 主版本 | 正式发布时设为 1 | +| MINOR | 模块号 | M1=0, M2=1, M3=2... | +| PATCH | 任务号 | 每个任务完成时 +1 | + +### 版本与模块对应 + +| 模块 | 版本范围 | 任务数 | 描述 | +|------|----------|--------|------| +| M1 | 0.0.1 ~ 0.0.5 | 5 | 基础架构 | +| M2 | 0.1.1 ~ 0.1.9 | 9 | 划词核心 | +| M3 | 0.2.1 ~ 0.2.11 | 11 | 词典系统 | +| M4 | 0.3.1 ~ 0.3.8 | 8 | Popup查词 | +| M5 | 0.4.1 ~ 0.4.16 | 16 | 设置系统 | +| M6 | 0.5.1 ~ 0.5.7 | 7 | 触发方式 | +| M7 | 0.6.1 ~ 0.6.6 | 6 | 右键菜单 | +| M8 | 0.7.1 ~ 0.7.10 | 10 | 生词本 | +| M9 | 0.8.1 ~ 0.8.7 | 7 | API账号 | +| M10 | 0.9.1 ~ 0.9.8 | 8 | 高级功能 | +| M11 | 0.10.1 ~ 1.0.0 | 10 | 优化发布 | + +**总计**: 97个验收点 → 最终版本 `1.0.0` + +### 版本流程示例 +``` +开始: 0.0.0 +M1.1完成 → 0.0.1 +... +M1.5完成 → 0.0.5 (M1完成) +M2.1完成 → 0.1.1 (进入M2,MINOR+1) +... +M11.10完成 → 1.0.0 (正式发布) +``` + +--- + +## 当前状态 + +**当前版本**: `0.0.1` +**当前进度**: 1/97 (1%) +**下一任务**: [M1.2 Manifest V3 配置](./M1.md#m12-manifest-v3-配置--目标版本-0002) + +--- + +## 文档索引 + +### 核心规范(必读) +| 文档 | 内容 | +|------|------| +| [AGENTS.md](./AGENTS.md) | 架构原则、代码风格、通信协议、安全规范 | +| [QUICK_REF.md](./QUICK_REF.md) | 版本速查、命名规范、代码模板 | + +### 模块开发计划 +| 文档 | 版本范围 | 任务数 | 关键产出 | +|------|----------|--------|----------| +| [M1.md](./M1.md) | 0.0.1-0.0.5 | 5 | 项目框架、构建配置、通信机制 | +| [M2.md](./M2.md) | 0.1.1-0.1.9 | 9 | 划词检测、图标、基础面板 | +| [M3.md](./M3.md) | 0.2.1-0.2.11 | 11 | 词典基类、必应/有道实现 | +| [M4.md](./M4.md) | 0.3.1-0.3.8 | 8 | Popup界面、搜索、历史、独立窗口 | +| [M5.md](./M5.md) | 0.4.1-0.4.16 | 16 | 6页设置系统 | +| [M6.md](./M6.md) | 0.5.1-0.5.7 | 7 | 多种触发方式配置 | +| [M7.md](./M7.md) | 0.6.1-0.6.6 | 6 | 右键菜单系统 | +| [M8.md](./M8.md) | 0.7.1-0.7.10 | 10 | 生词本、导入导出 | +| [M9.md](./M9.md) | 0.8.1-0.8.7 | 7 | 第三方API账号配置 | +| [M10.md](./M10.md) | 0.9.1-0.9.8 | 8 | 剪贴板、PDF支持、权限管理 | +| [M11.md](./M11.md) | 0.10.1-1.0.0 | 10 | 性能优化、国际化、发布 | + +### 版本记录 +| 文档 | 内容 | +|------|------| +| [VERSION.md](./VERSION.md) | 所有任务的完成状态和历史记录 | + +--- + +## 开发流程 + +1. **阅读规范**: 开始前阅读 [AGENTS.md](./AGENTS.md) 和 [QUICK_REF.md](./QUICK_REF.md) +2. **查看模块**: 根据当前版本打开对应的模块文件(如 [M1.md](./M1.md)) +3. **开发实现**: 按任务顺序实现,每个任务完成更新版本号 +4. **提交验收**: 用户确认后更新 VERSION.md 并提交 commit + +### Commit 格式 +```bash +feat(M1.1): 任务描述 (v0.0.1) +``` + +--- + +## 快速命令 + +```bash +# 开发 +npm run dev + +# 构建 +npm run build + +# 版本更新(手动) +# 1. 修改 package.json version +# 2. 修改 manifest.json version +# 3. 更新 VERSION.md 任务状态 +# 4. git commit -m "feat(Mx.x): 描述 (vx.x.x)" +``` diff --git a/docs/VERSION.md b/docs/VERSION.md new file mode 100644 index 0000000..f7a3586 --- /dev/null +++ b/docs/VERSION.md @@ -0,0 +1,195 @@ +# 版本记录 + +> 97个验收点状态跟踪 + +--- + +## 当前版本 + +**版本**: `0.0.0` +**状态**: 🟡 初始状态 +**进度**: 0/97 (0%) +**下一目标**: [M1.1 项目初始化](./M1.md#m11) + +--- + +## M1 基础架构 (0.0.1 - 0.0.5) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M1.1 | 0.0.1 | 项目初始化 | ✅ | 2026-02-09 | +| M1.2 | 0.0.2 | Manifest V3 配置 | ⬜ | - | +| M1.3 | 0.0.3 | 构建工具配置 | ⬜ | - | +| M1.4 | 0.0.4 | 模块间通信工具 | ⬜ | - | +| M1.5 | 0.0.5 | 开发环境验证 | ⬜ | - | + +--- + +## M2 划词核心 (0.1.1 - 0.1.9) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M2.1 | 0.1.1 | 文本选择检测 | ⬜ | - | +| M2.2 | 0.1.2 | 获取选中文本坐标 | ⬜ | - | +| M2.3 | 0.1.3 | 沙拉图标组件 | ⬜ | - | +| M2.4 | 0.1.4 | 图标定位显示 | ⬜ | - | +| M2.5 | 0.1.5 | 图标点击事件 | ⬜ | - | +| M2.6 | 0.1.6 | 基础面板组件 | ⬜ | - | +| M2.7 | 0.1.7 | 面板位置计算 | ⬜ | - | +| M2.8 | 0.1.8 | 图标-面板联动 | ⬜ | - | +| M2.9 | 0.1.9 | 图标显示开关 | ⬜ | - | + +--- + +## M3 词典系统 (0.2.1 - 0.2.11) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M3.1 | 0.2.1 | 词典接口基类 | ⬜ | - | +| M3.2 | 0.2.2 | 词典管理器 | ⬜ | - | +| M3.3 | 0.2.3 | 必应词典(Mock) | ⬜ | - | +| M3.4 | 0.2.4 | 后台查询接口 | ⬜ | - | +| M3.5 | 0.2.5 | 结果展示组件 | ⬜ | - | +| M3.6 | 0.2.6 | 点击图标查词(Mock) | ⬜ | - | +| M3.7 | 0.2.7 | 必应词典真实API | ⬜ | - | +| M3.8 | 0.2.8 | 加载状态显示 | ⬜ | - | +| M3.9 | 0.2.9 | 有道词典实现 | ⬜ | - | +| M3.10 | 0.2.10 | 结果折叠/展开 | ⬜ | - | +| M3.11 | 0.2.11 | 词典图标标识 | ⬜ | - | + +--- + +## M4 Popup查词 (0.3.1 - 0.3.8) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M4.1 | 0.3.1 | Popup基础界面 | ⬜ | - | +| M4.2 | 0.3.2 | Popup搜索功能 | ⬜ | - | +| M4.3 | 0.3.3 | 搜索建议 | ⬜ | - | +| M4.4 | 0.3.4 | 查询历史记录 | ⬜ | - | +| M4.5 | 0.3.5 | 历史记录展示 | ⬜ | - | +| M4.6 | 0.3.6 | 前进后退导航 | ⬜ | - | +| M4.7 | 0.3.7 | 收藏按钮 | ⬜ | - | +| M4.8 | 0.3.8 | 独立窗口打开 | ⬜ | - | + +--- + +## M5 设置系统 (0.4.1 - 0.4.16) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M5.1 | 0.4.1 | 设置页面框架 | ⬜ | - | +| M5.2 | 0.4.2 | 配置存储工具 | ⬜ | - | +| M5.3 | 0.4.3 | 划词翻译开关 | ⬜ | - | +| M5.4 | 0.4.4 | 动画开关 | ⬜ | - | +| M5.5 | 0.4.5 | 后台运行 | ⬜ | - | +| M5.6 | 0.4.6 | 黑暗模式 | ⬜ | - | +| M5.7 | 0.4.7 | 界面语言 | ⬜ | - | +| M5.8 | 0.4.8 | 输入框排除 | ⬜ | - | +| M5.9 | 0.4.9 | 触摸模式 | ⬜ | - | +| M5.10 | 0.4.10 | 划词语言 | ⬜ | - | +| M5.11 | 0.4.11 | 记忆折叠 | ⬜ | - | +| M5.12 | 0.4.12 | 双击间隔 | ⬜ | - | +| M5.13 | 0.4.13 | 已选词典列表 | ⬜ | - | +| M5.14 | 0.4.14 | 添加词典 | ⬜ | - | +| M5.15 | 0.4.15 | 词典排序 | ⬜ | - | +| M5.16 | 0.4.16 | 词典删除 | ⬜ | - | + +--- + +## M6 触发方式 (0.5.1 - 0.5.7) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M6.1 | 0.5.1 | 显示图标 | ⬜ | - | +| M6.2 | 0.5.2 | 图标悬停查词 | ⬜ | - | +| M6.3 | 0.5.3 | 图标位置偏移 | ⬜ | - | +| M6.4 | 0.5.4 | 直接搜索模式 | ⬜ | - | +| M6.5 | 0.5.5 | 双击搜索模式 | ⬜ | - | +| M6.6 | 0.5.6 | 快捷键搜索模式 | ⬜ | - | +| M6.7 | 0.5.7 | 鼠标悬浮取词 | ⬜ | - | + +--- + +## M7 右键菜单 (0.6.1 - 0.6.6) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M7.1 | 0.6.1 | 右键菜单注册 | ⬜ | - | +| M7.2 | 0.6.2 | 沙拉查词子菜单 | ⬜ | - | +| M7.3 | 0.6.3 | 网页翻译菜单 | ⬜ | - | +| M7.4 | 0.6.4 | 自定义右键菜单 | ⬜ | - | +| M7.5 | 0.6.5 | 右键菜单排序 | ⬜ | - | +| M7.6 | 0.6.6 | 右键菜单开关 | ⬜ | - | + +--- + +## M8 生词本 (0.7.1 - 0.7.10) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M8.1 | 0.7.1 | 收藏功能实现 | ⬜ | - | +| M8.2 | 0.7.2 | 生词本数据库 | ⬜ | - | +| M8.3 | 0.7.3 | 生词本页面 | ⬜ | - | +| M8.4 | 0.7.4 | 生词本搜索 | ⬜ | - | +| M8.5 | 0.7.5 | 生词本删除 | ⬜ | - | +| M8.6 | 0.7.6 | 导出JSON | ⬜ | - | +| M8.7 | 0.7.7 | 导出CSV | ⬜ | - | +| M8.8 | 0.7.8 | 导出Anki | ⬜ | - | +| M8.9 | 0.7.9 | 生词本导入 | ⬜ | - | +| M8.10 | 0.7.10 | 收藏上下文 | ⬜ | - | + +--- + +## M9 API账号 (0.8.1 - 0.8.7) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M9.1 | 0.8.1 | 账号配置页面 | ⬜ | - | +| M9.2 | 0.8.2 | 百度翻译API | ⬜ | - | +| M9.3 | 0.8.3 | 彩云小译API | ⬜ | - | +| M9.4 | 0.8.4 | 搜狗翻译API | ⬜ | - | +| M9.5 | 0.8.5 | 腾讯翻译君API | ⬜ | - | +| M9.6 | 0.8.6 | 有道翻译API | ⬜ | - | +| M9.7 | 0.8.7 | API密钥加密存储 | ⬜ | - | + +--- + +## M10 高级功能 (0.9.1 - 0.9.8) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M10.1 | 0.9.1 | 权限管理页面 | ⬜ | - | +| M10.2 | 0.9.2 | 读取剪贴板权限 | ⬜ | - | +| M10.3 | 0.9.3 | 剪贴板快速查词 | ⬜ | - | +| M10.4 | 0.9.4 | 写入剪贴板权限 | ⬜ | - | +| M10.5 | 0.9.5 | 复制原文功能 | ⬜ | - | +| M10.6 | 0.9.6 | 复制译文功能 | ⬜ | - | +| M10.7 | 0.9.7 | PDF支持 | ⬜ | - | +| M10.8 | 0.9.8 | 独立窗口完善 | ⬜ | - | + +--- + +## M11 优化发布 (0.10.1 - 1.0.0) + +| 任务 | 版本 | 描述 | 状态 | 日期 | +|------|------|------|------|------| +| M11.1 | 0.10.1 | 请求去重 | ⬜ | - | +| M11.2 | 0.10.2 | 请求取消 | ⬜ | - | +| M11.3 | 0.10.3 | 虚拟滚动 | ⬜ | - | +| M11.4 | 0.10.4 | 错误日志 | ⬜ | - | +| M11.5 | 0.10.5 | 国际化框架 | ⬜ | - | +| M11.6 | 0.10.6 | 英文翻译 | ⬜ | - | +| M11.7 | 0.10.7 | 使用文档 | ⬜ | - | +| M11.8 | 0.10.8 | 开发文档 | ⬜ | - | +| M11.9 | 0.10.9 | 打包配置 | ⬜ | - | +| M11.10 | 1.0.0 | 图标和素材 | ⬜ | - | + +--- + +## 统计 + +- **总计**: 97 个任务 +- **已完成**: 0 +- **剩余**: 97 +- **当前进度**: 0% diff --git a/package.json b/package.json new file mode 100644 index 0000000..65bbf99 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "salad-dict", + "version": "0.0.1", + "description": "聚合词典划词翻译", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint . --ext .js,.vue" + }, + "dependencies": { + "vue": "^3.4.0", + "vue-router": "^4.2.0", + "pinia": "^2.1.0", + "localforage": "^1.10.0" + }, + "devDependencies": { + "@crxjs/vite-plugin": "^2.0.0", + "@vitejs/plugin-vue": "^5.0.0", + "vite": "^5.0.0", + "eslint": "^8.56.0", + "eslint-plugin-vue": "^9.19.0" + }, + "keywords": [ + "chrome-extension", + "dictionary", + "translation" + ], + "author": "", + "license": "MIT" +} diff --git a/ui/1-POPUP.png b/ui/1-POPUP.png new file mode 100644 index 0000000..e87f611 Binary files /dev/null and b/ui/1-POPUP.png differ diff --git a/ui/10-SETTINGS-SearchModes.png b/ui/10-SETTINGS-SearchModes.png new file mode 100644 index 0000000..4505e7d Binary files /dev/null and b/ui/10-SETTINGS-SearchModes.png differ diff --git a/ui/11-SETTINGS-Dictionaries.png b/ui/11-SETTINGS-Dictionaries.png new file mode 100644 index 0000000..3dd6cab Binary files /dev/null and b/ui/11-SETTINGS-Dictionaries.png differ diff --git a/ui/12-SETTINGS-DictAuths.png b/ui/12-SETTINGS-DictAuths.png new file mode 100644 index 0000000..d30996f Binary files /dev/null and b/ui/12-SETTINGS-DictAuths.png differ diff --git a/ui/13-SETTINGS-ContextMenus.png b/ui/13-SETTINGS-ContextMenus.png new file mode 100644 index 0000000..ac38cb2 Binary files /dev/null and b/ui/13-SETTINGS-ContextMenus.png differ diff --git a/ui/14-SETTINGS-Permissions.png b/ui/14-SETTINGS-Permissions.png new file mode 100644 index 0000000..0e6ada6 Binary files /dev/null and b/ui/14-SETTINGS-Permissions.png differ diff --git a/ui/2-POPUP.png b/ui/2-POPUP.png new file mode 100644 index 0000000..9c9e9f3 Binary files /dev/null and b/ui/2-POPUP.png differ diff --git a/ui/3-POPUP.png b/ui/3-POPUP.png new file mode 100644 index 0000000..08c2f6e Binary files /dev/null and b/ui/3-POPUP.png differ diff --git a/ui/4-POPUP.png b/ui/4-POPUP.png new file mode 100644 index 0000000..0eafcd3 Binary files /dev/null and b/ui/4-POPUP.png differ diff --git a/ui/5-INJECT-ICON.png b/ui/5-INJECT-ICON.png new file mode 100644 index 0000000..0903eb5 Binary files /dev/null and b/ui/5-INJECT-ICON.png differ diff --git a/ui/6-INJECT-MAIN.png b/ui/6-INJECT-MAIN.png new file mode 100644 index 0000000..f6d68c1 Binary files /dev/null and b/ui/6-INJECT-MAIN.png differ diff --git a/ui/7-ContextMenus.png b/ui/7-ContextMenus.png new file mode 100644 index 0000000..0defdc3 Binary files /dev/null and b/ui/7-ContextMenus.png differ diff --git a/ui/8-QuickSearch.png b/ui/8-QuickSearch.png new file mode 100644 index 0000000..f27411a Binary files /dev/null and b/ui/8-QuickSearch.png differ diff --git a/ui/9-SETTINGS-General.png b/ui/9-SETTINGS-General.png new file mode 100644 index 0000000..3b63c63 Binary files /dev/null and b/ui/9-SETTINGS-General.png differ