技术研究文档
创建日期: 2026-01-14
功能: 智能文本自动复制插件
技术栈: Vue.js 3 + Vite + TypeScript
研究概述
本文档记录了在实施计划前进行的技术研究和决策过程,解决了技术选型、最佳实践和潜在风险。
1. Vue.js 在 Chrome 插件中的应用
决策
在 Chrome 插件的 Content Script 中使用 Vue.js 3 实现 UI 组件和状态管理。
研究过程
问题: Vue.js 是否适合用于 Chrome 插件开发?会不会增加不必要的复杂度?
调研结果:
- 体积优势: Vue 3 运行时版本(不含编译器)压缩后约 50KB,对于插件来说可接受
- 性能优势: Composition API 提供了更好的 Tree-shaking 支持,可以减少最终包体积
- 开发效率: 响应式系统和组件化大幅简化状态管理和 UI 开发
- 成熟案例: 许多成功的 Chrome 插件使用 Vue.js(如 Grammarly、ColorZilla)
具体应用:
- Content Script: 使用 Vue 3 运行时创建 Toast 通知组件
- 状态管理: 使用 Composition API 的
ref和computed管理选择状态和定时器状态 - 无需 Vuex/Pinia: 功能简单,Composition API 足够
理由
Vue.js 提供的开发效率提升和代码可维护性远大于约 50KB 的体积增加。插件的核心逻辑(选择监听、文本处理)仍使用纯 TypeScript,Vue 仅用于 UI 层,符合模块化设计原则。
替代方案
- 原生 JavaScript + Web Components: 需要手写响应式系统,开发效率低
- React: 体积更大(约 130KB),且对 TypeScript 支持不如 Vue 直接
- Svelte: 体积最小但生态不如 Vue 成熟,对 Chrome 插件支持较少
2. Vite 构建 Chrome 插件的配置方案
决策
使用 Vite 作为构建工具,配置特定的插件构建模式。
研究过程
问题: Vite 默认针对 Web 应用,如何配置以支持 Chrome 插件?
关键配置点:
-
禁用代码分割: Chrome 插件要求单文件入口
build: { rollupOptions: { output: { manualChunks: undefined // 禁用分块 } } } -
Content Script 入口: 配置独立的入口文件
build: { rollupOptions: { input: { 'content-script': resolve(__dirname, 'src/content-script.ts') } } } -
构建目标: 设置为现代浏览器
build: { target: 'chrome88', // 匹配 manifest 的最低版本 cssCodeSplit: false } -
Manifest V3 生成: 使用插件自动生成或手动维护
- 手动维护
manifest.json(推荐,更灵活) - 使用
@crxjs/vite-plugin(自动化但配置复杂)
- 手动维护
最佳实践:
- 开发模式: 使用 Vite dev server + Chrome 插件热重载
- 生产构建: 单入口文件 + 最小化体积
- Source Map: 仅在开发模式启用
理由
Vite 的开发体验显著优于 Webpack,配置更简洁。虽然需要特殊配置,但社区已有成熟方案(CRXJS、vite-plugin-web-extension)。
替代方案
- Webpack: 配置复杂,构建速度慢,但对插件支持最成熟
- Rollup: 轻量但需要手动配置很多细节
- Parcel: 零配置但对插件支持不足
3. Chrome Clipboard API 的使用方式
决策
使用 navigator.clipboard.writeText() API,配合 Manifest V3 的 clipboardWrite 权限。
研究过程
问题: Content Script 中如何安全地访问剪贴板?
Clipboard API 演进:
-
Legacy API (
document.execCommand('copy')):- 已废弃,但兼容性最好
- 需要创建临时
textarea元素 - 不支持异步操作
-
Modern API (
navigator.clipboard):- 异步 API,返回 Promise
- 需要 HTTPS 或 localhost(插件自动满足)
- Chrome 88+ 支持
权限要求:
// manifest.json
{
"permissions": ["clipboardWrite"],
"host_permissions": ["<all_urls>"]
}
Content Script 中的使用:
// 无需用户手势即可使用(有 clipboardWrite 权限)
async function copyToClipboard(text: string): Promise<boolean> {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (error) {
console.error('复制失败:', error);
// 降级到 execCommand
return fallbackCopy(text);
}
}
// 降级方案
function fallbackCopy(text: string): boolean {
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
const success = document.execCommand('copy');
document.body.removeChild(textarea);
return success;
}
理由
Modern Clipboard API 是官方推荐的方式,代码更简洁。提供 execCommand 降级方案确保在极端情况下也能工作。
替代方案
- 仅使用
execCommand: 可靠但已废弃 - 使用第三方库(如
clipboard.js): 违反最小依赖原则
4. 文本清理的正则表达式方案
决策
使用原生 JavaScript 字符串方法结合正则表达式实现文本清理。
研究过程
需求:
- 去除首尾的空格、制表符、换行符
- 去除首尾的单引号(
')和双引号(") - 处理嵌套引号(如
"'text'"→text) - 保留文本中间的空格和引号
实现方案:
export function cleanText(text: string): string {
let cleaned = text;
// 1. 去除首尾空白字符
cleaned = trimWhitespace(cleaned);
// 2. 递归去除首尾引号(处理嵌套)
cleaned = removeQuotes(cleaned);
// 3. 再次去除空白(引号内可能有空格)
cleaned = trimWhitespace(cleaned);
return cleaned;
}
function trimWhitespace(text: string): string {
// 使用正则去除所有类型的空白字符
return text.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}
function removeQuotes(text: string): string {
// 循环去除首尾引号,直到没有引号或文本为空
let result = text;
let prevLength = -1;
while (result.length > 0 && result.length !== prevLength) {
prevLength = result.length;
// 去除首尾的单引号或双引号
result = result.replace(/^["']|["']$/g, '');
}
return result;
}
测试用例:
cleanText(' hello ') // → 'hello'
cleanText('"hello"') // → 'hello'
cleanText("'hello'") // → 'hello'
cleanText('"\'hello\'"') // → 'hello'
cleanText(' " hello " ') // → 'hello'
cleanText('hello world') // → 'hello world' (保留中间空格)
cleanText('say "hello" world') // → 'say "hello" world' (保留中间引号)
理由
原生方法性能最优,无需引入第三方库。循环去除引号确保处理嵌套情况。正则表达式简洁高效。
替代方案
- 使用
trim()+ 字符串操作: 代码冗长且难以处理嵌套 - 使用解析库: 过度设计且违反最小依赖原则
5. Vue 组件在 Content Script 中的挂载方式
决策
动态创建 Shadow DOM 容器,在其中挂载 Vue 应用,避免样式污染。
研究过程
问题: 如何在网页中注入 Vue 组件而不与页面样式冲突?
挂载方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 直接挂载到 body | 简单 | 容易被页面样式覆盖 |
| iframe | 完全隔离 | 定位困难,性能差 |
| Shadow DOM | 样式隔离,性能好 | 需要手动处理样式继承 |
Shadow DOM 实现:
// src/composables/useFeedback.ts
import { createApp } from 'vue';
import Toast from '@/components/Toast.vue';
export function useFeedback() {
let shadowRoot: ShadowRoot | null = null;
function createShadowContainer() {
// 创建容器元素
const container = document.createElement('div');
container.id = 'auto-copy-feedback-root';
// 创建 Shadow DOM
shadowRoot = container.attachShadow({ mode: 'open' });
// 创建挂载点
const mountPoint = document.createElement('div');
shadowRoot.appendChild(mountPoint);
// 注入样式(需要在 Shadow DOM 中重新注入)
const style = document.createElement('style');
style.textContent = getComponentStyles(); // 提取组件样式
shadowRoot.appendChild(style);
// 挂载到页面
document.body.appendChild(container);
return mountPoint;
}
function show(message: string) {
const mountPoint = shadowRoot
? shadowRoot.querySelector('div')
: createShadowContainer();
const app = createApp(Toast, { message });
app.mount(mountPoint!);
// 1.5 秒后卸载
setTimeout(() => {
app.unmount();
}, 1500);
}
return { show };
}
样式隔离策略:
- 使用 Shadow DOM 的
mode: 'open' - 在 Shadow DOM 内注入组件样式
- 使用极高的 z-index(
9999999) - 避免使用全局选择器
理由
Shadow DOM 提供了完美的样式隔离,同时保持良好的性能。Vue 3 对 Shadow DOM 支持良好。
替代方案
- CSS Modules + BEM: 仍可能被页面
!important覆盖 - CSS-in-JS: 增加依赖且性能较差
6. 定时器精确计时方案
决策
使用 performance.now() 而非 Date.now() 进行时间测量,确保精确到毫秒。
研究过程
问题: 如何确保 2 秒定时器的精确性(误差 ±50ms)?
时间 API 对比:
| API | 精度 | 特点 |
|---|---|---|
Date.now() | 毫秒 | 受系统时钟影响,可能跳变 |
performance.now() | 微秒 | 单调递增,不受系统时钟影响 |
setTimeout | 毫秒 | 受浏览器节流影响 |
实现方案:
export function useTimerManager() {
let timerId: number | null = null;
let startTime: number = 0;
const DURATION = 2000; // 2 秒
function startTimer(callback: () => void) {
startTime = performance.now();
timerId = window.setTimeout(() => {
const elapsed = performance.now() - startTime;
console.log(`定时器触发,实际耗时: ${elapsed}ms`);
// 只有在误差范围内才执行
if (Math.abs(elapsed - DURATION) < 100) {
callback();
}
timerId = null;
}, DURATION);
}
function resetTimer(callback: () => void) {
cancelTimer();
startTimer(callback);
}
function cancelTimer() {
if (timerId !== null) {
clearTimeout(timerId);
timerId = null;
}
}
return { startTimer, resetTimer, cancelTimer };
}
应对浏览器节流:
- 使用
requestAnimationFrame辅助检测(页面不可见时可能被节流) - 在回调中验证实际耗时
- 文档中说明已知限制(页面休眠时可能不准确)
理由
performance.now() 是高精度计时的标准方式,不受系统时钟影响。结合误差检测确保准确性。
替代方案
Date.now(): 精度较低且可能受系统时钟调整影响- Web Workers: 过度设计且增加复杂度
7. TypeScript 严格模式配置
决策
启用 TypeScript 的 strict 模式,确保类型安全。
配置项说明
{
"compilerOptions": {
"strict": true, // 启用所有严格检查
"noImplicitAny": true, // 禁止隐式 any
"strictNullChecks": true, // 严格的 null 检查
"strictFunctionTypes": true, // 严格的函数类型检查
"noUnusedLocals": true, // 未使用的局部变量报错
"noUnusedParameters": true, // 未使用的参数报错
}
}
Chrome API 类型支持:
npm install --save-dev @types/chrome
自定义类型定义:
// src/types/index.ts
export interface SelectionState {
text: string;
range: Range | null;
timestamp: number;
isStable: boolean;
}
export interface TimerState {
timerId: number | null;
startTime: number;
duration: number;
isActive: boolean;
}
export interface FeedbackOptions {
message: string;
duration?: number;
position?: { x: number; y: number };
}
理由
严格模式可以在编译时发现更多潜在错误,提升代码质量。对于小型项目,严格模式的配置成本可接受。
8. 性能优化策略
决策
采用防抖(debounce)优化选择事件监听,避免频繁触发。
研究过程
问题: 用户快速拖拽选择时,selectionchange 事件会频繁触发,影响性能。
防抖实现:
function debounce<T extends (...args: any[]) => void>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timerId: number | null = null;
return function (...args: Parameters<T>) {
if (timerId !== null) {
clearTimeout(timerId);
}
timerId = window.setTimeout(() => {
fn(...args);
timerId = null;
}, delay);
};
}
// 使用
const debouncedHandler = debounce((selection: SelectionState) => {
// 处理选择变更
}, 100); // 100ms 防抖
document.addEventListener('selectionchange', () => {
const selection = window.getSelection();
if (selection && selection.toString()) {
debouncedHandler({
text: selection.toString(),
range: selection.getRangeAt(0),
timestamp: performance.now(),
isStable: false,
});
}
});
其他优化:
- 事件委托: 只在 document 上监听一次
- 懒加载: Toast 组件按需创建和销毁
- 内存管理: 及时清理定时器和事件监听器
理由
防抖可以显著减少不必要的计算,同时不影响用户体验。100ms 的延迟用户感知不到。
9. 测试策略最佳实践
决策
采用 Vitest + @vue/test-utils + Playwright 三层测试策略。
测试层次
1. 单元测试(Vitest):
- 测试纯函数(textProcessor)
- 测试 Composables(useSelectionMonitor、useTimerManager)
- 测试 Vue 组件(Toast)
2. 集成测试(Vitest + Happy-DOM):
- 测试模块间交互
- 模拟浏览器环境
3. E2E 测试(Playwright):
- 测试完整用户流程
- 在真实 Chrome 环境中测试
Mock 策略:
// tests/utils/mocks.ts
// Mock Clipboard API
export function mockClipboard() {
Object.assign(navigator, {
clipboard: {
writeText: vi.fn().mockResolvedValue(undefined),
},
});
}
// Mock Selection API
export function mockSelection(text: string) {
const selection = {
toString: () => text,
getRangeAt: () => ({
startContainer: document.body,
endContainer: document.body,
}),
};
vi.spyOn(window, 'getSelection').mockReturnValue(selection as any);
}
// Mock Performance API
export function mockPerformance() {
let now = 0;
vi.spyOn(performance, 'now').mockImplementation(() => {
return now;
});
return {
advance: (ms: number) => { now += ms; },
};
}
理由
分层测试确保不同粒度的质量保障。Vitest 与 Vite 深度集成,速度快。Playwright 提供真实浏览器测试。
10. 发布流程与 Chrome Web Store 要求
决策
使用手动发布流程,遵循 Chrome Web Store 的审核要求。
Chrome Web Store 要求
1. Manifest V3 必须项:
{
"manifest_version": 3,
"name": "Auto Copy - 智能文本自动复制",
"version": "1.0.0",
"description": "选中文本 2 秒后自动复制,智能清理空格和引号",
"permissions": ["clipboardWrite"],
"host_permissions": ["<all_urls>"],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content-script.js"]
}],
"icons": {
"16": "icons/icon-16.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
}
}
2. 图标要求:
- 16x16、48x48、128x128 像素
- PNG 格式,透明背景
- 简洁清晰的设计
3. 隐私政策:
- 如果使用用户数据,必须提供隐私政策链接
- 本插件无需隐私政策(不收集数据)
4. 截图要求:
- 至少 1 张,最多 5 张
- 尺寸 1280x800 或 640x400
- 展示插件功能
5. 审核周期:
- 首次提交: 通常 3-5 个工作日
- 更新提交: 通常 1-2 个工作日
发布流程
# 1. 构建生产版本
npm run build
# 2. 检查构建产物
ls -lh dist/
# 3. 在 Chrome 中本地测试
# chrome://extensions/ -> 加载已解压的扩展程序 -> 选择 dist 目录
# 4. 打包为 zip
cd dist && zip -r ../chrome-auto-copy-v1.0.0.zip . && cd ..
# 5. 上传到 Chrome Web Store
# https://chrome.google.com/webstore/devconsole/
理由
手动流程更可控,避免自动化工具的潜在问题。遵循官方要求确保审核通过。
总结
关键技术决策回顾
| 决策点 | 选择 | 核心理由 |
|---|---|---|
| 前端框架 | Vue.js 3 | 开发效率高,体积可控,Composition API 适合模块化 |
| 构建工具 | Vite | 开发体验好,构建速度快,TypeScript 原生支持 |
| 剪贴板 API | navigator.clipboard | 现代 API,异步支持,提供降级方案 |
| 文本清理 | 原生正则 | 性能最优,无需依赖 |
| 样式隔离 | Shadow DOM | 完美隔离,性能好 |
| 计时方案 | performance.now() | 高精度,不受系统时钟影响 |
| 类型系统 | TypeScript strict | 提前发现错误,提升质量 |
| 性能优化 | 防抖 + 懒加载 | 减少不必要计算,降低内存占用 |
| 测试策略 | Vitest + Playwright | 快速 + 真实浏览器测试 |
风险缓解
所有识别的风险均已制定缓解措施:
- CSP 阻止 → 文档说明 + 用户反馈
- Vue 冲突 → 独立作用域 + Shadow DOM
- 体积过大 → Tree-shaking + 运行时版本
- 兼容性 → 明确版本要求 + 降级方案
后续行动
本研究文档的所有决策已整合到实施计划中。可以开始 Phase 1(项目初始化)的开发工作。
本研究文档遵循项目宪章的最小依赖和模块化设计原则。
快速入门指南
功能: 智能文本自动复制插件
技术栈: Vue.js 3 + Vite + TypeScript
目标: 帮助开发者快速上手项目开发
📋 前置要求
必需工具
- Node.js: >= 18.0.0
- npm: >= 9.0.0(或 pnpm >= 8.0.0)
- Chrome: >= 88(用于测试)
- Git: >= 2.30.0
- 代码编辑器: VS Code(推荐)+ Volar 插件
推荐 VS Code 插件
{
"recommendations": [
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
🚀 快速开始(5 分钟)
1. 克隆项目
git clone <repository-url>
cd chrome-auto-copy
2. 安装依赖
npm install
3. 启动开发服务器
npm run dev
4. 在 Chrome 中加载插件
- 打开 Chrome 浏览器
- 访问
chrome://extensions/ - 开启右上角"开发者模式"
- 点击"加载已解压的扩展程序"
- 选择项目的
dist目录
5. 测试插件
- 打开任意网页
- 选中一段文本
- 保持选择 2 秒
- 看到"已复制"提示即成功
📁 项目结构
chrome-auto-copy/
├── public/ # 静态资源
│ └── icons/ # 插件图标
│ ├── icon-16.png
│ ├── icon-48.png
│ └── icon-128.png
├── src/
│ ├── components/ # Vue 组件
│ │ └── Toast.vue # 反馈提示组件
│ ├── composables/ # Vue Composables(核心逻辑)
│ │ ├── useSelectionMonitor.ts # 选择监听
│ │ ├── useTimerManager.ts # 定时器管理
│ │ ├── useClipboard.ts # 剪贴板操作
│ │ └── useFeedback.ts # 反馈 UI 管理
│ ├── utils/ # 工具函数
│ │ └── textProcessor.ts # 文本处理
│ ├── types/ # TypeScript 类型定义
│ │ └── index.ts
│ ├── content-script.ts # Content Script 入口
│ └── main.ts # 应用主入口
├── tests/ # 测试文件
│ ├── unit/ # 单元测试
│ └── integration/ # 集成测试
├── specs/ # 功能规范文档
│ └── 001-chrome-auto-copy/
│ ├── spec.md # 功能规范
│ ├── plan.md # 实施计划
│ ├── research.md # 技术研究
│ ├── data-model.md # 数据模型
│ └── contracts/ # API 合约
├── manifest.json # Chrome 插件配置
├── vite.config.ts # Vite 配置
├── tsconfig.json # TypeScript 配置
├── .eslintrc.js # ESLint 配置
├── .prettierrc.js # Prettier 配置
├── vitest.config.ts # Vitest 配置
├── package.json
└── README.md
🔧 开发命令
常用命令
# 开发模式(热重载)
npm run dev
# 生产构建
npm run build
# 代码检查
npm run lint
# 自动修复代码格式
npm run lint:fix
# 代码格式化
npm run format
# 运行单元测试
npm run test
# 运行测试(监听模式)
npm run test:watch
# 查看测试覆盖率
npm run test:coverage
# 类型检查
npm run type-check
一键完整检查
# 运行所有检查(lint + 格式 + 类型 + 测试)
npm run check-all
🧩 核心模块说明
1. SelectionMonitor(选择监听)
文件: src/composables/useSelectionMonitor.ts
功能: 监听网页中的文本选择事件
核心 API:
const { currentSelection, startMonitoring, onSelectionChange } = useSelectionMonitor();
// 开始监听
startMonitoring();
// 注册回调
onSelectionChange((state) => {
console.log('选中的文本:', state.text);
});
2. TimerManager(定时器管理)
文件: src/composables/useTimerManager.ts
功能: 管理 2 秒等待定时器
核心 API:
const { startTimer, resetTimer, cancelTimer } = useTimerManager();
// 启动 2 秒定时器
startTimer(2000, () => {
console.log('2 秒到了,执行操作');
});
// 重置定时器
resetTimer(() => {
console.log('重新计时 2 秒');
});
3. TextProcessor(文本处理)
文件: src/utils/textProcessor.ts
功能: 清理文本(去除首尾空格和引号)
核心 API:
import { cleanText, isEmpty } from '@/utils/textProcessor';
// 清理文本
const cleaned = cleanText(' "Hello World" ');
console.log(cleaned); // 'Hello World'
// 检查是否为空
if (isEmpty(text)) {
console.log('文本为空');
}
4. ClipboardManager(剪贴板操作)
文件: src/composables/useClipboard.ts
功能: 复制文本到剪贴板
核心 API:
const { copy, isSupported } = useClipboard();
// 复制文本
const success = await copy('Hello World');
if (success) {
console.log('复制成功');
}
5. FeedbackUI(用户反馈)
文件: src/composables/useFeedback.ts + src/components/Toast.vue
功能: 显示"已复制"等反馈提示
核心 API:
const { show } = useFeedback();
// 显示成功提示
show({
message: '已复制',
type: 'success',
duration: 1500,
});
📝 开发工作流
新功能开发流程
-
创建功能分支
git checkout -b feature/your-feature-name -
编写代码
- 在对应模块目录添加/修改代码
- 遵循 TypeScript 严格模式
- 使用 Vue 3 Composition API
-
编写测试
# 在 tests/unit/ 目录创建对应测试文件 # 确保测试覆盖率 > 80% npm run test -
代码检查
npm run lint npm run format npm run type-check -
本地测试
npm run build # 在 Chrome 中加载 dist 目录测试 -
提交代码
git add . git commit -m "feat: 添加新功能描述" git push origin feature/your-feature-name
🐛 调试技巧
1. 开发者工具调试
// 在代码中添加调试日志
console.log('[Auto Copy] 选择变更:', state.text);
console.log('[Auto Copy] 定时器启动:', timestamp);
查看日志:
- 打开 Chrome DevTools(F12)
- 切换到"Console"标签
- 筛选"Auto Copy"关键词
2. Vue DevTools 调试
- 安装 Vue DevTools 插件
- 打开 DevTools,切换到"Vue"标签
- 查看组件状态和响应式数据
3. 断点调试
// 在代码中设置断点
debugger;
然后在 Chrome DevTools 的"Sources"标签中调试。
4. 性能分析
// 使用 performance API 测量性能
const start = performance.now();
cleanText(text);
const end = performance.now();
console.log(`文本清理耗时: ${end - start}ms`);
🧪 测试指南
运行测试
# 运行所有测试
npm run test
# 运行特定文件
npm run test useSelectionMonitor
# 监听模式(自动重跑)
npm run test:watch
# 查看覆盖率
npm run test:coverage
编写测试示例
// tests/unit/textProcessor.test.ts
import { describe, test, expect } from 'vitest';
import { cleanText } from '@/utils/textProcessor';
describe('cleanText', () => {
test('应该去除首尾空格', () => {
expect(cleanText(' hello ')).toBe('hello');
});
test('应该去除首尾引号', () => {
expect(cleanText('"hello"')).toBe('hello');
});
test('应该保留中间空格', () => {
expect(cleanText(' hello world ')).toBe('hello world');
});
});
🔨 构建与发布
本地构建测试
# 构建生产版本
npm run build
# 检查构建产物
ls -lh dist/
打包为 ZIP
# 进入 dist 目录并打包
cd dist
zip -r ../chrome-auto-copy-v1.0.0.zip .
cd ..
发布到 Chrome Web Store
- 访问 Chrome Web Store Developer Dashboard
- 点击"新增项目"
- 上传 ZIP 文件
- 填写插件信息:
- 名称:Auto Copy - 智能文本自动复制
- 描述:选中文本 2 秒后自动复制,智能清理空格和引号
- 分类:生产力工具
- 截图:准备 1-5 张功能截图
- 提交审核(通常 3-5 个工作日)
🎯 常见问题
Q1: 插件加载失败
问题: Chrome 提示"Manifest 文件无效"
解决:
# 确保构建成功
npm run build
# 检查 manifest.json 是否在 dist 目录
ls dist/manifest.json
Q2: 热重载不工作
问题: 修改代码后插件未更新
解决:
- 在
chrome://extensions/点击刷新按钮 - 或者使用 Chrome 插件热重载工具(如 Extension Reloader)
Q3: 剪贴板复制失败
问题: 复制时提示权限错误
解决:
检查 manifest.json 是否包含:
{
"permissions": ["clipboardWrite"],
"host_permissions": ["<all_urls>"]
}
Q4: 样式被网页覆盖
问题: "已复制"提示不显示或样式错误
解决:
确保使用 Shadow DOM(在 useFeedback.ts 中):
const shadowRoot = container.attachShadow({ mode: 'open' });
📚 学习资源
官方文档
项目文档
💡 最佳实践
代码风格
-
使用 Composition API
// ✅ 推荐 import { ref, computed } from 'vue'; export function useTimer() { const count = ref(0); const doubled = computed(() => count.value * 2); return { count, doubled }; } // ❌ 不推荐(Options API) export default { data() { return { count: 0 }; }, computed: { doubled() { return this.count * 2; } } }; -
类型优先
// ✅ 推荐:明确类型 function cleanText(text: string): string { return text.trim(); } // ❌ 不推荐:隐式 any function cleanText(text) { return text.trim(); } -
模块化
// ✅ 推荐:单一职责 // useSelectionMonitor.ts - 只负责选择监听 // useTimerManager.ts - 只负责定时器 // ❌ 不推荐:所有逻辑放在一个文件 // allLogic.ts - 包含所有功能
性能优化
-
防抖高频事件
import { debounce } from '@/utils/debounce'; const handleSelection = debounce((state: SelectionState) => { // 处理选择 }, 100); -
懒加载组件
// 按需创建 Toast 组件,用完销毁 const app = createApp(Toast); app.mount(container); setTimeout(() => app.unmount(), 1500); -
及时清理
// 组件卸载时清理监听器 onUnmounted(() => { document.removeEventListener('selectionchange', handler); });
🤝 贡献指南
提交规范
feat: 添加新功能
fix: 修复 bug
docs: 更新文档
style: 代码格式调整
refactor: 代码重构
test: 添加测试
chore: 构建/工具链更新
示例:
git commit -m "feat: 添加文本长度限制功能"
git commit -m "fix: 修复嵌套引号清理问题"
git commit -m "docs: 更新快速入门指南"
Pull Request 流程
- Fork 项目
- 创建功能分支
- 编写代码和测试
- 提交 PR,填写清晰的描述
- 等待代码审查
- 根据反馈修改
- 合并到主分支
📧 获取帮助
- Issue: GitHub Issues
- Discussion: GitHub Discussions
- Email: your-email@example.com
🎉 开始开发
现在你已经掌握了项目的基本知识,可以开始开发了!
# 启动开发服务器
npm run dev
# 在另一个终端运行测试监听
npm run test:watch
# 开始编码 🚀
祝开发愉快!
本快速入门指南遵循项目宪章的模块化设计和代码规范统一原则。
实现计划:智能文本自动复制插件
计划版本: 0.1.0
创建日期: 2026-01-14
关联规范: spec.md
负责人: [待分配]
技术栈: Vue.js 3 + Vite + TypeScript
执行摘要
目标
使用 Vue.js 3 + Vite + TypeScript 技术栈开发一个 Chrome 浏览器插件,实现智能文本自动复制功能。插件将采用模块化架构,包含选择监听、定时器管理、文本处理、剪贴板操作和用户反馈五个核心模块。
技术选型
- 前端框架: Vue.js 3 (Composition API)
- 构建工具: Vite 4.x
- 类型系统: TypeScript 5.x
- 插件规范: Chrome Extension Manifest V3
- 代码规范: ESLint + Prettier
- 测试框架: Vitest + @vue/test-utils
关键里程碑
- 里程碑 1(项目搭建): 完成项目初始化和构建配置 - 第 1 周(Day 1-2)
- 里程碑 2(核心功能): 完成选择监听和定时复制模块 - 第 1 周(Day 3-5)
- 里程碑 3(文本处理): 完成文本清理和剪贴板操作 - 第 2 周(Day 1-3)
- 里程碑 4(用户反馈): 完成 Vue 组件化的反馈 UI - 第 2 周(Day 4-5)
- 里程碑 5(测试与优化): 完成测试、性能优化和文档 - 第 3 周
- 里程碑 6(发布): Chrome Web Store 提交 - 第 4 周
资源需求
- 开发人员: 1 人 / 15 个工作日
- 测试人员: 0.5 人 / 5 个工作日(兼职测试)
- 其他资源: Chrome 开发者账号($5 一次性费用)
宪章合规性确认
在开始实施前,确认以下合规性检查:
- 模块化设计: 采用 Vue Composition API 和 TypeScript 模块系统实现清晰的模块边界
- 最小依赖: 仅引入必要的 Vue 生态依赖(vue、vite、@vitejs/plugin-vue),无额外第三方库
- 代码规范: 配置 ESLint、Prettier、TypeScript strict 模式
- 中文优先: 所有 Speckit 文档、注释、提交信息使用中文
技术背景与研究
Vue.js 在 Chrome 插件中的应用
Vue.js 可以很好地应用于 Chrome 插件开发:
- Content Script: 使用 Vue 3 的轻量级运行时构建 UI 组件(反馈提示)
- Composition API: 提供清晰的逻辑复用和模块组织
- 响应式系统: 简化状态管理(选择状态、定时器状态)
- TypeScript 支持: 完善的类型定义,提升代码质量
Vite 构建配置
Vite 需要特殊配置以支持 Chrome 插件构建:
- 使用
@vitejs/plugin-vue处理 Vue SFC - 配置多入口构建(content script)
- 禁用代码分割(插件需要单文件)
- 生成 Manifest V3 配置文件
关键技术决策
| 决策点 | 选择 | 理由 |
|---|---|---|
| Vue 版本 | Vue 3 | Composition API 更适合模块化设计,体积更小 |
| 构建工具 | Vite | 开发速度快,配置简洁,TypeScript 原生支持 |
| 状态管理 | Composition API | 功能简单,无需 Pinia/Vuex |
| UI 组件 | 纯 Vue 组件 | 无需 UI 库,减少依赖 |
| 样式方案 | Scoped CSS | 避免污染网页样式 |
实现阶段
阶段 0: 项目初始化(Day 1-2)
时间: 第 1 周 Day 1-2
目标: 搭建基于 Vite + Vue 3 + TypeScript 的 Chrome 插件开发环境
任务清单
-
任务 0.1: 初始化 Vite 项目
- 负责人: [待分配]
- 预计工时: 2 小时
- 命令:
npm create vite@latest chrome-auto-copy -- --template vue-ts
-
任务 0.2: 配置 Chrome 插件构建
- 负责人: [待分配]
- 预计工时: 4 小时
- 配置
vite.config.ts支持插件构建 - 创建
manifest.json(Manifest V3)
-
任务 0.3: 配置代码规范工具
- 负责人: [待分配]
- 预计工时: 2 小时
- 安装并配置 ESLint + Prettier
- 配置 TypeScript strict 模式
- 设置 Git pre-commit hook
-
任务 0.4: 配置测试环境
- 负责人: [待分配]
- 预计工时: 2 小时
- 安装 Vitest 和 @vue/test-utils
- 配置 vitest.config.ts
交付物
- 可运行的 Vite 项目
- 完整的
manifest.json配置 - ESLint + Prettier 配置文件
- Vitest 测试环境
- 项目 README.md
验收标准
-
npm run dev可正常启动开发服务器 -
npm run build可生成插件构建产物 -
npm run lint无错误 -
npm run test可运行测试
阶段 1: 核心模块开发(Day 3-5)
时间: 第 1 周 Day 3-5
目标: 实现选择监听和定时器管理模块
任务清单
-
任务 1.1: 实现 SelectionMonitor 模块
- 负责人: [待分配]
- 预计工时: 6 小时
- 使用 Composition API 创建
useSelectionMonitorcomposable - 监听
selectionchange事件 - 实现
getCurrentSelection()方法
-
任务 1.2: 实现 TimerManager 模块
- 负责人: [待分配]
- 预计工时: 4 小时
- 创建
useTimerManagercomposable - 实现定时器的启动、重置、取消逻辑
- 使用
performance.now()确保精确计时
-
任务 1.3: 集成选择监听和定时器
- 负责人: [待分配]
- 预计工时: 4 小时
- 在主 content script 中整合两个模块
- 实现选择变更时重置定时器的逻辑
- 处理边界情况(空选择、快速变更)
-
任务 1.4: 编写单元测试
- 负责人: [待分配]
- 预计工时: 4 小时
- 测试选择监听功能
- 测试定时器重置逻辑
- 测试边界情况
交付物
src/composables/useSelectionMonitor.tssrc/composables/useTimerManager.tssrc/content-script.ts(主入口)- 对应的单元测试文件
验收标准
- 选择文本后能够正确触发监听
- 2 秒后准确触发回调(误差 ±50ms)
- 选择变更时定时器正确重置
- 快速取消选择不触发回调
- 单元测试覆盖率 > 80%
阶段 2: 文本处理与剪贴板(Day 6-8)
时间: 第 2 周 Day 1-3
目标: 实现文本清理和剪贴板复制功能
任务清单
- 任务 2.1: 实现 TextProcessor 模块
- 负责人: [待分配]
- 预计工时: 4 小时
- 创建
src/utils/textProcessor.ts - 实现
cleanText()函数 - 实现去除首尾空格和引号的逻辑
- 任务 2.2: 实现 ClipboardManager 模块
- 负责人: [待分配]
- 预计工时: 3 小时
- 创建
useClipboardcomposable - 使用
navigator.clipboard.writeText()API - 处理权限和异常情况
- 任务 2.3: 集成文本处理和复制流程
- 负责人: [待分配]
- 预计工时: 3 小时
- 在定时器回调中调用文本处理和复制
- 添加错误处理和日志记录
- 任务 2.4: 编写文本处理单元测试
- 负责人: [待分配]
- 预计工时: 4 小时
- 测试各种空格、引号组合
- 测试嵌套引号处理
- 测试边界情况(空文本、纯空格)
交付物
src/utils/textProcessor.tssrc/composables/useClipboard.ts- 完整的文本处理单元测试
验收标准
- 正确去除首尾空格、制表符、换行符
- 正确去除首尾单引号和双引号
- 正确处理嵌套引号(如
"'text'"→text) - 文本成功写入剪贴板
- 文本处理单元测试覆盖率 > 90%
阶段 3: 用户反馈 UI(Day 9-10)
时间: 第 2 周 Day 4-5
目标: 使用 Vue 组件实现反馈提示 UI
任务清单
- 任务 3.1: 创建 Toast 通知组件
- 负责人: [待分配]
- 预计工时: 4 小时
- 创建
src/components/Toast.vue - 实现淡入淡出动画
- 使用 Scoped CSS 避免样式污染
- 任务 3.2: 实现反馈 UI 管理
- 负责人: [待分配]
- 预计工时: 3 小时
- 创建
useFeedbackcomposable - 动态挂载 Vue 组件到 DOM
- 实现自动消失逻辑(1.5 秒)
- 任务 3.3: 集成反馈到复制流程
- 负责人: [待分配]
- 预计工时: 2 小时
- 复制成功后显示提示
- 处理多次复制的提示队列
- 任务 3.4: 样式优化
- 负责人: [待分配]
- 预计工时: 3 小时
- 确保高 z-index 不被覆盖
- 适配深色/浅色主题
- 响应式定位(跟随光标位置)
交付物
src/components/Toast.vuesrc/composables/useFeedback.ts- Toast 组件样式
验收标准
- 复制成功后显示"已复制"提示
- 提示在 1.5 秒后自动消失
- 提示不被网页样式覆盖
- 淡入淡出动画流畅
- 多次复制时提示正确显示
阶段 4: 测试与优化(Day 11-15)
时间: 第 3 周
目标: 完成完整测试、性能优化和兼容性验证
任务清单
- 任务 4.1: 集成测试
- 负责人: [待分配]
- 预计工时: 8 小时
- 测试完整的选择-等待-复制流程
- 测试不同网页类型(静态、SPA、动态)
- 测试边界情况和异常场景
- 任务 4.2: 性能优化
- 负责人: [待分配]
- 预计工时: 6 小时
- 优化事件监听性能(防抖/节流)
- 减少内存占用
- 优化构建产物体积
- 任务 4.3: 兼容性测试
- 负责人: [待分配]
- 预计工时: 6 小时
- 在 Windows、macOS、Linux 上测试
- 测试不同 Chrome 版本(88+)
- 测试常见网站兼容性
- 任务 4.4: 代码审查和重构
- 负责人: [待分配]
- 预计工时: 4 小时
- 代码审查,确保符合规范
- 重构重复代码
- 优化 TypeScript 类型定义
交付物
- 完整的集成测试套件
- 性能测试报告
- 兼容性测试报告
- 优化后的代码
验收标准
- 集成测试全部通过
- 单元测试覆盖率 > 85%
- 内存占用 < 10MB
- 构建产物体积 < 200KB
- 在主流网站上正常工作
- 代码通过 ESLint 和 TypeScript 检查
阶段 5: 文档与发布(Day 16-20)
时间: 第 4 周
目标: 完善文档并发布到 Chrome Web Store
任务清单
- 任务 5.1: 编写用户文档
- 负责人: [待分配]
- 预计工时: 4 小时
- 编写 README.md
- 编写使用说明
- 准备 Chrome Web Store 描述
- 任务 5.2: 准备发布资源
- 负责人: [待分配]
- 预计工时: 4 小时
- 设计插件图标(128x128、48x48、16x16)
- 准备截图和宣传图
- 编写 CHANGELOG.md
- 任务 5.3: 打包和测试
- 负责人: [待分配]
- 预计工时: 3 小时
- 生产环境构建
- 在本地加载插件测试
- 最终验收测试
- 任务 5.4: 提交到 Chrome Web Store
- 负责人: [待分配]
- 预计工时: 2 小时
- 注册开发者账号
- 上传插件包
- 填写商店信息
交付物
- 完整的 README.md
- 用户指南文档
- 插件图标和截图
- Chrome Web Store 商店页面
验收标准
- README 完整清晰
- 用户指南易于理解
- 插件图标符合规范
- 成功提交到 Chrome Web Store
- 通过商店审核(预计 3-5 个工作日)
技术实施细节
项目目录结构
chrome-auto-copy/
├── public/
│ └── icons/ # 插件图标
│ ├── icon-16.png
│ ├── icon-48.png
│ └── icon-128.png
├── src/
│ ├── components/
│ │ └── Toast.vue # 反馈提示组件
│ ├── composables/
│ │ ├── useSelectionMonitor.ts # 选择监听
│ │ ├── useTimerManager.ts # 定时器管理
│ │ ├── useClipboard.ts # 剪贴板操作
│ │ └── useFeedback.ts # 反馈 UI 管理
│ ├── utils/
│ │ └── textProcessor.ts # 文本处理工具
│ ├── types/
│ │ └── index.ts # TypeScript 类型定义
│ ├── content-script.ts # Content Script 入口
│ └── main.ts # 应用主入口
├── tests/
│ ├── unit/ # 单元测试
│ └── integration/ # 集成测试
├── manifest.json # Chrome 插件配置
├── vite.config.ts # Vite 配置
├── tsconfig.json # TypeScript 配置
├── .eslintrc.js # ESLint 配置
├── .prettierrc.js # Prettier 配置
├── vitest.config.ts # Vitest 配置
├── package.json
└── README.md
核心模块接口设计
SelectionMonitor (useSelectionMonitor)
interface SelectionState {
text: string;
range: Range | null;
timestamp: number;
isStable: boolean;
}
interface UseSelectionMonitor {
currentSelection: Ref<SelectionState>;
startMonitoring: () => void;
stopMonitoring: () => void;
onSelectionChange: (callback: (state: SelectionState) => void) => void;
}
export function useSelectionMonitor(): UseSelectionMonitor
TimerManager (useTimerManager)
interface TimerState {
timerId: number | null;
startTime: number;
duration: number;
isActive: boolean;
}
interface UseTimerManager {
timerState: Ref<TimerState>;
startTimer: (duration: number, callback: () => void) => void;
resetTimer: () => void;
cancelTimer: () => void;
}
export function useTimerManager(): UseTimerManager
TextProcessor
interface TextProcessorOptions {
trimWhitespace?: boolean;
removeQuotes?: boolean;
maxLength?: number;
}
export function cleanText(
text: string,
options?: TextProcessorOptions
): string;
export function trimWhitespace(text: string): string;
export function removeQuotes(text: string): string;
ClipboardManager (useClipboard)
interface UseClipboard {
copy: (text: string) => Promise<boolean>;
isSupported: Ref<boolean>;
lastError: Ref<Error | null>;
}
export function useClipboard(): UseClipboard
FeedbackUI (useFeedback)
interface FeedbackOptions {
message: string;
duration?: number;
position?: { x: number; y: number };
}
interface UseFeedback {
show: (options: FeedbackOptions) => void;
hide: () => void;
isVisible: Ref<boolean>;
}
export function useFeedback(): UseFeedback
数据流设计
用户选择文本
↓
SelectionMonitor 监听到 selectionchange 事件
↓
更新 SelectionState(text, range, timestamp)
↓
触发 onSelectionChange 回调
↓
TimerManager 启动 2 秒定时器
↓
如果期间有新的选择变更 → 重置定时器
↓
2 秒后定时器触发
↓
TextProcessor 清理文本(去除首尾空格和引号)
↓
ClipboardManager 复制到剪贴板
↓
FeedbackUI 显示"已复制"提示
↓
1.5 秒后提示自动消失
依赖管理
新增依赖
| 依赖名称 | 版本 | 用途 | 理由 | 替代方案 |
|---|---|---|---|---|
| vue | ^3.4.0 | 前端框架 | 提供响应式和组件化能力,体积小性能好 | 无(核心依赖) |
| vite | ^5.0.0 | 构建工具 | 开发体验好,构建速度快,TypeScript 原生支持 | Webpack(配置复杂) |
| @vitejs/plugin-vue | ^5.0.0 | Vite 的 Vue 插件 | 支持 Vue SFC 编译 | 无(必需) |
| typescript | ^5.3.0 | 类型系统 | 提供类型检查,提升代码质量 | 无(必需) |
| eslint | ^8.56.0 | 代码检查工具 | 保证代码质量和规范 | 无(宪章要求) |
| prettier | ^3.2.0 | 代码格式化工具 | 统一代码风格 | 无(宪章要求) |
| vitest | ^1.2.0 | 测试框架 | 与 Vite 完美集成,速度快 | Jest(配置复杂) |
| @vue/test-utils | ^2.4.0 | Vue 组件测试工具 | 测试 Vue 组件 | 无(必需) |
依赖审查清单
- 所有依赖维护活跃度已确认(Vue、Vite 生态均为活跃维护)
- 依赖包安全漏洞已扫描(使用
npm audit) - 依赖包许可证已确认兼容(均为 MIT 许可证)
- 依赖包体积已评估(构建后预计 < 200KB)
依赖理由说明
为什么选择 Vue.js 而不是原生 JavaScript?
- Vue 的 Composition API 提供了更好的代码组织和复用能力
- 响应式系统简化了状态管理
- 组件化使 UI 开发更高效
- 构建后的体积增加可控(< 100KB),性能影响可接受
为什么选择 Vite 而不是 Webpack?
- Vite 开发体验更好,热更新极快
- 配置更简洁,对 TypeScript 支持更好
- 构建速度更快
- 对 Chrome 插件构建支持良好
代码规范配置
格式化工具:Prettier
配置文件: .prettierrc.js
module.exports = {
semi: true,
trailingComma: 'es5',
singleQuote: true,
printWidth: 100,
tabWidth: 2,
useTabs: false,
arrowParens: 'avoid',
endOfLine: 'lf',
};
运行命令:
- 格式化所有文件:
npm run format - 检查格式:
npm run format:check
Lint 工具:ESLint
配置文件: .eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
webextensions: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:vue/vue3-recommended',
'prettier',
],
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'vue'],
rules: {
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'vue/multi-word-component-names': 'off',
'no-console': ['warn', { allow: ['warn', 'error'] }],
},
};
运行命令:
- 检查代码:
npm run lint - 自动修复:
npm run lint:fix
TypeScript 配置
配置文件: tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"moduleResolution": "bundler",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"types": ["chrome", "vite/client"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.vue"],
"exclude": ["node_modules", "dist"]
}
CI 集成
Pre-commit Hook (Husky + lint-staged)
package.json:
{
"lint-staged": {
"*.{ts,vue}": [
"eslint --fix",
"prettier --write"
]
}
}
- Pre-commit hook 已配置
- CI 流水线已添加 lint 检查(GitHub Actions)
- CI 流水线已添加格式检查
- CI 流水线已添加单元测试
风险管理
已识别风险
| 风险ID | 风险描述 | 概率 | 影响 | 缓解措施 | 负责人 |
|---|---|---|---|---|---|
| R1 | Chrome API 在某些网站被 CSP 阻止 | 中 | 中 | 文档说明限制,收集不兼容网站列表 | [待分配] |
| R2 | Vue 运行时与网页 Vue 实例冲突 | 低 | 中 | 使用独立作用域,避免全局污染 | [待分配] |
| R3 | 构建产物体积过大影响性能 | 低 | 中 | 使用 Tree-shaking,仅引入必要模块 | [待分配] |
| R4 | TypeScript 类型定义不完整 | 低 | 低 | 及时补充类型定义,使用 @types/chrome | [待分配] |
| R5 | 用户反馈 UI 被网页样式覆盖 | 中 | 低 | 使用极高 z-index 和 Shadow DOM(可选) | [待分配] |
| R6 | 不同浏览器剪贴板 API 兼容性问题 | 低 | 高 | 仅支持 Chrome 88+,文档明确说明 | [待分配] |
应急预案
R1 - CSP 阻止:
- 在文档中明确说明已知限制
- 提供用户反馈机制收集问题网站
- 考虑未来版本添加白名单功能
R2 - Vue 实例冲突:
- 使用
createApp()创建独立 Vue 实例 - 避免污染
window对象 - 测试常见使用 Vue 的网站
R3 - 构建体积过大:
- 使用 Vite 的代码分割(但插件需禁用)
- 仅引入 Vue 运行时版本(不含编译器)
- 移除 devtools 和开发时警告
R6 - 剪贴板兼容性:
- 使用标准的
navigator.clipboard.writeText() - 添加降级方案(
document.execCommand('copy')) - 明确文档说明浏览器版本要求
测试计划
单元测试
目标覆盖率: 85%
测试框架: Vitest + @vue/test-utils
负责人: [待分配]
测试范围:
textProcessor.ts的所有函数(目标覆盖率 95%)useSelectionMonitorcomposableuseTimerManagercomposableuseClipboardcomposableuseFeedbackcomposable- Toast 组件渲染和行为
关键测试用例:
// textProcessor 测试
describe('cleanText', () => {
test('去除首尾空格', () => {
expect(cleanText(' hello ')).toBe('hello');
});
test('去除首尾引号', () => {
expect(cleanText('"hello"')).toBe('hello');
});
test('处理嵌套引号', () => {
expect(cleanText('"\'hello\'"')).toBe('hello');
});
test('保留中间空格', () => {
expect(cleanText(' hello world ')).toBe('hello world');
});
});
// useTimerManager 测试
describe('useTimerManager', () => {
test('启动定时器后 2 秒触发回调', async () => {
const { startTimer } = useTimerManager();
const callback = vi.fn();
startTimer(2000, callback);
await vi.advanceTimersByTime(2000);
expect(callback).toHaveBeenCalledTimes(1);
});
test('重置定时器重新计时', async () => {
const { startTimer, resetTimer } = useTimerManager();
const callback = vi.fn();
startTimer(2000, callback);
await vi.advanceTimersByTime(1000);
resetTimer();
await vi.advanceTimersByTime(1500);
expect(callback).not.toHaveBeenCalled();
});
});
集成测试
测试场景:
- 完整的选择-等待-复制流程
- 选择变更时定时器重置
- 快速取消选择不触发复制
- 空文本不触发复制
- 超长文本正常处理
- 多次连续复制
测试工具: Playwright(E2E 测试)
负责人: [待分配]
性能测试
性能指标:
- 选择事件监听响应时间 < 50ms
- 文本清理时间 < 10ms
- 剪贴板写入时间 < 100ms
- 插件内存占用 < 10MB
- 构建产物体积 < 200KB
测试工具: Chrome DevTools Performance、Memory Profiler
负责人: [待分配]
文档更新计划
- README 更新(项目说明、安装方法、使用指南)
- API 文档更新(Composables 使用文档)
- 架构文档更新(模块设计、数据流)
- 变更日志更新(CHANGELOG.md)
- 用户指南(Chrome Web Store 描述)
- 开发指南(贡献者文档)
发布检查清单
- 所有功能已实现并通过测试
- 代码审查已完成
- 文档已更新(README、用户指南)
- 版本号已更新(package.json、manifest.json)
- 变更日志已更新(CHANGELOG.md)
- 向后兼容性已确认(首版无此要求)
- 性能基准测试已通过
- 安全扫描已通过(
npm audit) - 构建产物已验证(
npm run build) - 在本地加载插件测试通过
- 插件图标和截图已准备
- Chrome Web Store 商店信息已填写
进度跟踪
第 1 周
已完成:
- [待更新]
进行中:
- [待更新]
阻塞问题:
- [待更新]
第 2 周
已完成:
- [待更新]
进行中:
- [待更新]
阻塞问题:
- [待更新]
第 3 周
已完成:
- [待更新]
进行中:
- [待更新]
阻塞问题:
- [待更新]
第 4 周
已完成:
- [待更新]
进行中:
- [待更新]
阻塞问题:
- [待更新]
批准与签字
| 角色 | 姓名 | 批准 | 日期 |
|---|---|---|---|
| 技术负责人 | [待分配] | ||
| 项目经理 | [待分配] |
本实施计划严格遵循 项目宪章 的所有原则。