36b6bfd20d
* feat: 生成成功改为 toast 提示 * refactor: 数据预览改为显示示例数据,简化组件逻辑 * fix: 非必填字段预览显示 null * fix: 修复空值率与必填状态的逻辑 * fix: 切换为非必填时默认空值率 100% * feat: 字段编辑弹窗添加「完成」按钮 去除关闭按钮,添加取消按钮 * refactor: 删除未使用的 defaultNullRate 功能 * feat: 优化规则管理功能 * fix: 更新 features 测试断言以匹配新增的 testDataGenerator * refactor: 将 formatFileSize 重命名为 formatBytes 并移至通用工具模块 * refactor: 使用 Label 组件替换原生 label 元素,并在 DecodeResultPaper 中引入 Input 组件 * refactor: 规范化页面组件目录结构 * refactor(JsonTools): 规范化页面组件目录结构 * refactor(StorageCleaner): 规范化页面组件目录结构 * refactor(Timestamp): 规范化页面组件目录结构 * refactor(i18n): 移除 chrome.i18n 国际化,统一使用中文硬编码 * refactor(AppRoot): 移除 RouterProvider 组件,直接渲染子组件 * fix(RouterProvider): 将 goBack 重命名为 goHome,修复跨窗同步 merge 不一致 * fix(ThemeModeProvider): 修复主题快照同步与首屏闪烁问题 * refactor: 将 UI 文案改为中文并优化相关逻辑 * refactor: 清理代码注释并优化组件结构 * feat(Dashboard): 重构仪表板功能组件和逻辑 * refactor: 更新功能键名称并移除 README 文件 * refactor: 重构 TopBar 组件并更新项目结构 * feat(TopBar): 添加搜索功能组件并优化结构 * refactor: 统一使用 Button 组件替换原有 button 元素 * feat: 添加 EmptyPlaceholder 组件并更新相关页面 * feat(TextStatistics): 引入 StatCard 组件以优化统计信息展示 * feat(Timestamp): 重构时间戳转换功能,新增 ConverterForm 组件 * feat(Jwt): 重构 JWT 组件,新增常量和结果视图 * refactor(RightClickRestorer): 用状态配置表简化页面 UI 结构 * fix(business): 修复 skewedRandom 函数中的数学计算错误 * refactor(ImageUploader): 移除预览 URL 相关逻辑并简化粘贴事件处理 * feat(TestDataGenerator): 更新规则编辑提示和警告显示逻辑 * refactor(CopyButton.test): 移除冗余测试用例 * refactor(RouterProvider, chromeStorage, useContextMenuData): 更新存储获取逻辑以移除默认值参数 * refactor(代码重复): 抽取共享工具函数与 UI 组件,消除多处重复实现 * fix(RouterProvider): 修复初始加载状态逻辑,确保在加载前不覆盖 chrome.storage * feat(TopBar): 添加搜索框快捷键提示功能及相关测试 * refactor(StorageCleaner): 移动 isRestrictedUrl 函数到独立模块并更新相关引用 * fix(StorageCleaner): 修复 IndexedDB 清理竞态、部分成功计数与刷新后状态同步 * fix: 修复路由初始化竞态、存储状态静默覆盖与存储清理误删 * refactor: 统一中文文案并简化组件结构,提升代码可读性 * refactor: 更新 Worker 消息类型以支持生成任务 ID * fix: 修复 ruleStorage 写入失败处理与 CopyButton 成功态样式
193 lines
9.7 KiB
Markdown
193 lines
9.7 KiB
Markdown
# AGENTS.md
|
||
|
||
WXT 浏览器扩展项目 (React 19 + TypeScript)。提供时间戳转换、存储清理、JWT 解析、JSON 工具、二维码、Base64、测试数据生成器等测试效率工具。
|
||
|
||
## 核心命令
|
||
|
||
```bash
|
||
npm run dev # Chrome 开发模式 (HMR)
|
||
npm run dev:firefox # Firefox 开发模式
|
||
npm run build # Chrome 生产构建
|
||
npm run build:firefox # Firefox 生产构建
|
||
npm run zip # 打包 Chrome 扩展 (.output/*.zip)
|
||
npm run zip:firefox # 打包 Firefox 扩展
|
||
npm run lint # ESLint (--max-warnings=0)
|
||
npm run typecheck # tsc --noEmit
|
||
npm run test # vitest run (单次执行)
|
||
npm run test:watch # vitest 监视模式
|
||
npm run test:coverage # 带覆盖率的测试
|
||
npx vitest run path/to/file.test.ts # 运行单个测试文件
|
||
npx wxt prepare # 重新生成 .wxt/ 类型声明(npm install 时 postinstall 会自动执行)
|
||
```
|
||
|
||
修改 `package.json` 或首次克隆仓库后需执行 `npm install`,会自动触发 `postinstall` → `wxt prepare`。
|
||
|
||
## 验证流程
|
||
|
||
详见 [CI 配置](./.github/CI.md)。本地与 CI 的检查层次如下。
|
||
|
||
### Pre-commit(`.husky/pre-commit`)
|
||
|
||
1. 后台运行 `tsc --noEmit`(不阻塞提交,结果输出到 stderr)
|
||
2. 前台运行 `lint-staged`:
|
||
- 代码文件 (`*.{ts,tsx,js,jsx,mjs}`):`eslint --fix --max-warnings=0`,再 `prettier --write`
|
||
- 其他文件 (`*.{json,css,scss,md}`):`prettier --write`
|
||
|
||
### Pre-push(`.husky/pre-push`)
|
||
|
||
1. 全项目 `tsc --noEmit`(阻塞推送)
|
||
2. 对本次推送相对 upstream(或 `origin/main`)变更的 `*.{ts,tsx,js,jsx,mjs}` 文件运行 `eslint --max-warnings=0`
|
||
|
||
### CI(GitHub Actions)
|
||
|
||
1. `setup` — 安装依赖
|
||
2. 并行 `lint`、`typecheck`(含 `wxt prepare`)、`test`
|
||
3. `build` — Chrome + Firefox 矩阵构建(仅当步骤 2 全部通过)
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
src/ # 源代码根目录
|
||
config/features.tsx # 功能定义(路由 + 元数据的单一事实来源)
|
||
entrypoints/ # 扩展入口点 (popup/, sidepanel/, background.ts, content.ts)
|
||
layout/ # 应用壳层布局(TopBar 导航、搜索、主题切换)
|
||
pages/ # 功能页面组件 (懒加载)
|
||
components/ # 可复用 UI 组件
|
||
components/ui/ # shadcn/ui 基础组件 (button, dialog, select 等)
|
||
providers/ # React Context (Router, Theme 等)
|
||
hooks/ # 自定义 React Hooks
|
||
utils/ # 工具函数与服务抽象
|
||
types/ # TypeScript 类型声明
|
||
lib/ # 通用工具函数(cn、utils)及数据生成器定义
|
||
workers/ # Web Worker(数据生成等耗时任务)
|
||
spec/ # 功能规格、修复方案与验收标准(见 spec/README.md)
|
||
public/ # 静态资源(图标等)
|
||
.wxt/ # wxt prepare 自动生成,含类型声明与扩展 tsconfig(勿手动编辑)
|
||
.output/ # 生产构建输出目录
|
||
```
|
||
|
||
### layout/
|
||
|
||
应用壳层,与 popup / sidepanel / tab 入口绑定。当前含 `TopBar/`(搜索、主题切换、返回导航、「在标签页打开」),遵循与 `pages/` 相同的 UI + Hook 模式。详见 [layout/README.md](./src/layout/README.md)。
|
||
|
||
### spec/
|
||
|
||
功能规格与验收标准文档,重大改动前优先查阅。索引见 [spec/README.md](./spec/README.md)。
|
||
|
||
### 页面组件模式
|
||
|
||
典型功能页面遵循 **UI + Hook 分离** 模式。详见 [CODING_STANDARDS.md § 11](./.github/CODING_STANDARDS.md#11-页面开发规范)。
|
||
|
||
```
|
||
src/pages/FeatureName/
|
||
├── index.tsx # 页面 UI(纯展示,仅负责渲染布局)
|
||
├── useFeatureName.ts # 业务逻辑 Hook(状态管理 + 转换逻辑)
|
||
├── constants.ts # 常量定义(可选,≥3 个常量时创建)
|
||
└── __tests__/
|
||
└── index.test.tsx
|
||
```
|
||
|
||
- 页面入口组件统一命名为 `Index`,通过 `export default function Index()` 导出
|
||
- Hook 负责所有状态管理和业务逻辑,通过返回值暴露给页面
|
||
- 子组件可以独立调用全局 Hook
|
||
- 当 `index.tsx` 超过 150 行时,必须拆分为 UI + Hook 模式
|
||
- 复杂页面可增加 `contexts/`、`hooks/`、`components/` 子目录
|
||
|
||
### 测试数据生成器模块
|
||
|
||
```
|
||
src/pages/TestDataGenerator/
|
||
├── index.tsx # 主页面(字段配置 + 标签页切换)
|
||
├── hooks/useGenerator.ts # Web Worker 管理 Hook(创建、复用、通信、销毁)
|
||
└── components/
|
||
├── FieldList.tsx # 字段列表(虚拟滚动 + @dnd-kit 拖拽排序 + 规则保存)
|
||
├── FieldItem.tsx # 字段卡片展示
|
||
├── FieldEditor.tsx # 字段编辑器(名称校验、生成器选择、参数配置)
|
||
├── GeneratorSelector.tsx # 生成器选择器(分类 + 搜索)
|
||
├── GeneratorConfig.tsx # 生成器参数表单(动态渲染 string/number/boolean/select/array)
|
||
├── GenerateOptions.tsx # 生成选项(数量、格式)
|
||
├── GenerateButton.tsx # 生成按钮 + 进度条
|
||
├── DataPreview.tsx # 示例数据预览(JSON 语法高亮)
|
||
├── ResultPanel.tsx # 生成结果状态面板
|
||
├── ExportPanel.tsx # 导出面板(复制/下载 JSON/CSV)
|
||
└── RuleManager.tsx # 规则管理(CRUD、搜索、导入/导出)
|
||
|
||
src/utils/
|
||
├── ruleStorage.ts # 规则持久化存储(localStorage)
|
||
└── dataExporter.ts # 数据导出工具(JSON/CSV 转换、下载、剪贴板)
|
||
|
||
src/lib/generators/ # 内置生成器定义(个人信息、企业、技术、基础类型)
|
||
|
||
src/workers/
|
||
└── generator.worker.ts # 数据生成 Web Worker
|
||
|
||
src/types/
|
||
└── testDataGenerator.ts # 类型定义(FieldConfig, DataRule, GeneratorDefinition 等)
|
||
```
|
||
|
||
## 关键架构决策
|
||
|
||
**路由**: 不使用 React Router。通过 `src/config/features.tsx` 的 `FEATURES` 数组管理,`RouterProvider` 根据 `PageType`
|
||
渲染对应组件。支持三种渲染模式:popup(弹窗)、sidepanel(侧边栏)和 tab(浏览器新标签页,TopBar「在标签页打开」调用 `openExtensionPage('popup.html', { mode: 'tab' })`,由 `getEntryPointType()` 根据 URL 参数 `mode=tab` 识别)。
|
||
每种模式有独立的路由和可见页面配置(`app/popupRoute`、`app/sidepanelRoute`、`app/tabRoute` 等)。
|
||
|
||
**存储**: 所有 Chrome Storage 键必须在 `src/types/storage.d.ts` 的 `StorageSchema` 中定义,键名使用 kebab-case 格式(如 `app/currentRoute`)。
|
||
使用 `src/utils/chromeStorage.ts` 及其 Hook。Router 同时使用 `chrome.storage.local` 和 `localStorage` 快照(`snapshot/{key}`)消除首屏闪烁。
|
||
异步加载完成前禁止写入 storage(`RouterProvider` 的 `canPersistRef`、`useStorageState` 的 `loadSucceededRef`),避免默认值覆盖已有数据。
|
||
|
||
**通信**: 使用 `@webext-core/messaging`,协议定义在 `src/utils/messages.ts`。
|
||
|
||
**路径别名**: `@/` 映射到 `src/` 目录(已在 `.wxt/tsconfig.json` 和 `vitest.config.ts` 中配置)。项目根目录使用 `@@/`。
|
||
|
||
**浏览器兼容**: 优先使用 `wxt/browser` 导出的 `browser` 对象,而非原生 `chrome` API。
|
||
|
||
## 测试环境
|
||
|
||
- 环境: jsdom
|
||
- 全局变量: `vitest/globals` (describe, it, expect 等无需导入)
|
||
- Setup 文件: `vitest.setup.ts` 自动 mock:
|
||
- `chrome.*` / `browser.*` API (storage, tabs, runtime, cookies 等)
|
||
- `window.matchMedia`
|
||
- 测试文件命名: `__tests__/*.test.{ts,tsx}` 或 `*.test.{ts,tsx}`
|
||
- Mock 模式: 使用 `vi.mock()` 进行模块级 mock,避免在测试文件中重复 mock 代码
|
||
- 测试工具: `@testing-library/react` + `@testing-library/user-event` 进行组件测试
|
||
|
||
## UI 文案
|
||
|
||
项目已移除 `chrome.i18n`,UI 文案直接在代码中使用中文。
|
||
|
||
- **功能元数据**: `src/config/features.tsx` 的 `FEATURES` 数组定义 `label`、`description`(用于 Dashboard 卡片与搜索)
|
||
- **页面文案**: 在组件 JSX、`constants.ts` 或 Hook 中直接写中文
|
||
- **Manifest 文案**: 扩展名称与描述在 `wxt.config.ts` 的 `manifest` 中维护
|
||
- **Toast / 错误提示**: 在 Hook 或 `constants.ts` 中定义,使用 `sonner` 的 `toast()` 展示
|
||
|
||
## 新功能开发清单
|
||
|
||
1. 在 `src/types/storage.d.ts` 添加 `PageType` 联合类型
|
||
2. 在 `src/config/features.tsx` 的 `FEATURES` 数组添加配置(指定 key、label、description、图标、三种渲染模式的组件)
|
||
3. 在 `src/pages/` 创建页面组件 (懒加载):
|
||
- `index.tsx` — UI 组件(纯展示)
|
||
- `useFeatureName.ts` — 业务逻辑 Hook
|
||
- `constants.ts` — 常量定义(可选,≥3 个常量时创建)
|
||
4. 如需新权限,更新 `wxt.config.ts` 的 `manifest.permissions`
|
||
5. 添加对应的单元测试
|
||
|
||
## 代码规范
|
||
|
||
- 禁止使用 `any` (测试文件除外)
|
||
- 未使用变量/参数: 使用 `_` 前缀 (如 `_unused`)
|
||
- 样式: 使用 Tailwind CSS + shadcn/ui (通过 `className` 和 `cn()` 工具)
|
||
- UI 组件: 优先使用 `src/components/ui/` 下的 shadcn/ui 组件 (button, dialog, select 等)
|
||
- 图标: 使用 `lucide-react` 图标库
|
||
- 格式: Prettier [配置](./.prettierrc)
|
||
- ESLint 使用 `typescript-eslint` 的 `projectService: true`
|
||
- Git Commit: 使用中文描述,遵循 [Conventional Commits 规范](https://www.conventionalcommits.org/zh-hans/v1.0.0/)
|
||
|
||
## 关键外部库(非显而易见的)
|
||
|
||
- `@webext-core/messaging` — 扩展消息通信
|
||
- `@dnd-kit` — 拖拽排序(用于页面顺序管理和字段列表排序)
|
||
- `qrious` + `qr-scanner` — 二维码生成与解析
|
||
- `dayjs` — 日期处理(时间戳转换)
|
||
- `sonner` — Toast 通知
|