docs: 同步工程文档与当前架构 (#70)

* docs(工程文档): 同步当前架构说明
* docs(工程文档): 格式化文档表格
This commit is contained in:
cursor[bot]
2026-06-26 16:59:53 +08:00
committed by GitHub
parent a163297de4
commit 5ae9cf065f
11 changed files with 181 additions and 101 deletions
+42 -38
View File
@@ -285,8 +285,7 @@ import { useThemeMode } from '@/providers/ThemeModeProvider';
import { FeatureConfig, FEATURES } from '@/config/features';
import { storageUtil } from '@/utils/chromeStorage';
// 5. i18n
import { useTranslation } from 'react-i18next';
import { normalizeLanguage, SUPPORTED_LANGUAGES } from '@/i18n';
import { useI18n } from '@/utils/chromeI18n';
// 6. 本地组件
import TextMode from './TextMode';
import { ZONES } from './constants';
@@ -295,7 +294,7 @@ import SwitchButtonGroup from '@/components/SwitchButtonGroup';
import { Button } from '@/components/ui/button';
// 8. 工具函数 / Hook
import { cn } from '@/lib/utils';
import { useLazyTranslation } from '@/utils/useLazyTranslation';
import { useStorageState } from '@/utils/useStorageState';
// 9. 类型
import type { PageType, StorageSchema } from '@/types/storage';
```
@@ -401,22 +400,22 @@ className={cn(
## 5. 错误处理
### 5.1 工具函数:结果对象模式
### 5.1 工具函数:可恢复错误返回可判断结果
工具函数**不抛异常**,返回包含 `hasError``error` 字段的结果对象:
可恢复的解析/校验错误应返回可判断的结果,避免工具层直接弹 Toast。确需保留底层异常的函数
(如 `formatJson` / `minifyJson`)必须在页面 Hook 或 UI 层捕获并转换为用户提示:
```typescript
// ✅ 结果对象模式
export function markdownToHtml(markdown: string): MarkdownToHtmlResult {
// ✅ 可恢复校验返回错误消息,调用方据此展示 UI
export function validateJson(text: string): string | null {
if (!text.trim()) {
return null;
}
try {
...
return { html, originalLength, htmlLength, hasError: false };
} catch (error) {
return {
html: '', ...
hasError: true,
error: error instanceof Error ? error.message : 'Markdown 解析失败',
};
JSON.parse(text.trim());
return null;
} catch (e) {
return e instanceof SyntaxError ? e.message : 'Invalid JSON';
}
}
```
@@ -658,7 +657,7 @@ export function useTimestampConverter(): UseTimestampConverterReturn { ... }
```
src/utils/useStorageState.ts — Chrome Storage 状态持久化
src/utils/useLazyTranslation.ts — i18n 懒加载
src/utils/chromeI18n.ts — chrome.i18n wrapper 与 useI18n
src/utils/useContextMenuData.ts — 右键菜单数据
src/utils/useDebounce.ts — 防抖
src/pages/Timestamp/useTimestampConverter.ts — 页面级 Hook
@@ -671,43 +670,48 @@ src/pages/StorageCleaner/useStorageCleaner.ts — 页面级 Hook
### 9.1 翻译键格式
- 命名空间:`common`(默认)、`features`
- 翻译键格式:`namespace:key`(如 `features:timestamp.title`
- 语言:`zh`(默认)、`en`
- 使用 Chrome 扩展标准的 `chrome.i18n`,通过 `src/utils/chromeI18n.ts` 暴露 `useI18n`
- 翻译 key 存放在 `public/_locales/zh_CN/messages.json`
- 直接 key`t('dashboard_title')` → 查找 `dashboard_title`
- 命名空间兼容写法:`t('common:buttons.search')` → 查找 `common_buttons_search`
- 命名空间参数:`useI18n(['common', 'features'])` 会尝试 `common_key``features_key`
### 9.2 翻译文件结构
```
i18n/locales/{zh,en}/common.json — 全局通用翻译
i18n/locales/{zh,en}/features.json — 功能模块标题和描述
i18n/locales/{zh,en}/{功能名}.json — 各功能独立翻译
public/_locales/zh_CN/messages.json — Chrome 扩展默认语言包
wxt.config.ts — manifest.default_locale = 'zh_CN'
```
### 9.3 使用方式
```typescript
// ✅ 页面组件 — 使用 useLazyTranslation
import { useLazyTranslation } from '@/utils/useLazyTranslation';
// ✅ 页面组件 / 子组件 — 使用 useI18n
import { useI18n } from '@/utils/chromeI18n';
export default function Index() {
const { t } = useLazyTranslation('timestamp');
return <h1>{t('timestamp:title')}</h1>;
const { t } = useI18n('timestamp');
return <h1>{t('timestamp_title')}</h1>;
}
// ✅ 全局组件 — 使用 useTranslation
import { useTranslation } from 'react-i18next';
export function TopBar() {
const { t } = useTranslation(['common', 'features']);
return <span>{t('common:settings')}</span>;
// ✅ 带占位符
export function NotFoundMessage() {
const { t } = useI18n('router');
return <p>{t('router_notFoundDescription', { entryPointType: 'popup' })}</p>;
}
```
### 9.4 添加新翻译
1.`i18n/locales/{zh,en}/features.json` 添加功能标题和描述
2. 创建 `i18n/locales/{zh,en}/{功能名}.json` 添加功能专属翻译
3.`utils/useLazyTranslation.ts``localeModules` 中注册新命名空间
1.`public/_locales/zh_CN/messages.json` 添加 Chrome 扩展格式的消息:
```json
{
"feature_title": { "message": "功能标题" },
"feature_description": { "message": "功能描述" }
}
```
2. key 使用下划线分隔,避免点号;`useI18n` 会把 `namespace:key.path` 兼容转换为下划线
3. `chrome.i18n` 不支持运行时动态切换语言,浏览器语言变化后需要刷新扩展页面
---
@@ -1083,7 +1087,7 @@ export default function Index() {
4. ✅ 业务逻辑提取到 `useXxx.ts` Hookindex.tsx 不超过 150 行)
5. ✅ 需要持久化的 UI 状态使用 `useStorageState`
6. ✅ 常量 ≥3 个时提取到 `constants.ts`
7. ✅ 在 `i18n/locales/{zh,en}/` 添加翻译
7. ✅ 在 `public/_locales/zh_CN/messages.json` 添加翻译
8. ✅ 创建 `__tests__/index.test.tsx` 测试文件
9. ✅ 如需新权限,更新 `wxt.config.ts` 的 `manifest.permissions`
10. ✅ 运行 `npm run lint && npm run typecheck && npm run test` 全部通过
@@ -1103,8 +1107,8 @@ export default function Index() {
| `src/hooks/` | 自定义 React Hooks |
| `src/utils/` | 工具函数与服务抽象 |
| `src/types/` | TypeScript 类型声明 |
| `src/lib/` | 通用工具函数(cn、utils |
| `public/` | 静态资源 |
| `src/lib/` | 通用工具函数与生成器库cn、utils、generators |
| `public/` | 静态资源与 Chrome `_locales` 语言包 |
---
+11 -12
View File
@@ -1,6 +1,6 @@
# Copilot 指令
基于 WXT 框架的浏览器扩展项目(React 19 + TypeScript),为开发者和测试人员提供效率工具:时间戳转换、存储清理、JWT 解析、JSON 工具、二维码、Base64、Markdown 等。
基于 WXT 框架的浏览器扩展项目(React 19 + TypeScript),为开发者和测试人员提供效率工具:时间戳转换、存储清理、JWT 解析、JSON 工具、二维码、Base64、测试数据生成器等。
## 核心命令
@@ -74,10 +74,10 @@ pages/FeatureName/
1.`types/storage.d.ts``PageType` 联合类型中添加新成员
2.`config/features.tsx``FEATURES` 数组中添加配置(key、翻译键、图标、三种渲染模式组件)
3.`pages/` 目录创建页面组件(懒加载):
- `index.tsx` — 使用 `useLazyTranslation` 的 UI 组件
- `index.tsx` — 使用 `useI18n` 的 UI 组件
- `useFeatureName.ts` — 业务逻辑 Hook
- `constants.ts` — 常量(可选)
4.`i18n/locales/{zh,en}/features.json` 添加翻译(复杂功能可新建独立 JSON 文件)
4.`public/_locales/zh_CN/messages.json` 添加 Chrome i18n 翻译
5. 如需新权限,更新 `wxt.config.ts``manifest.permissions`
6. 添加对应的单元测试
@@ -102,7 +102,7 @@ pages/FeatureName/
### 代码分割
`wxt.config.ts` 通过 `manualChunksForHtmlOnly()` 自动分组 vendor 依赖(vendor-react、vendor-i18n、vendor-qr、vendor-dnd),无需手动配置。
`wxt.config.ts` 通过 `manualChunksForHtmlOnly()` 自动分组 vendor 依赖(vendor-react、vendor-qr、vendor-dnd),无需手动配置。
### 代码风格
@@ -118,8 +118,7 @@ pages/FeatureName/
- 全局变量:`vitest/globals`describe、it、expect 等无需导入)
- Setup 文件:`vitest.setup.ts` 自动 mock 以下内容:
- `chrome.*` / `browser.*` APIstorage、tabs、runtime、cookies 等)
- `react-i18next`(返回 key 作为翻译)
- `@/utils/useLazyTranslation`(返回 `ns:key` 格式)
- `@/utils/chromeI18n`(从 `public/_locales/zh_CN/messages.json` 加载真实翻译)
- `window.matchMedia`
- 测试文件命名:`__tests__/*.test.{ts,tsx}``*.test.{ts,tsx}`
- 使用 `vi.mock()` 进行模块级 mock;避免重复 mock `vitest.setup.ts` 中已有的内容
@@ -127,12 +126,12 @@ pages/FeatureName/
### 国际化(i18n
- 命名空间:`common`(默认)、`features`
- 翻译键格式:`namespace:key`(如 `features:timestamp.title`
- 语言:`zh`(默认)、`en`
- 翻译文件:`i18n/locales/{zh,en}/{common,features}.json` + 各功能独立 JSON 文件
- 使用 `useLazyTranslation` Hook 加载功能专属翻译
- 回退策略:缺失的翻译键回退到 `zh`,若仍缺失则返回占位格式 `namespace:key`
- 使用 Chrome 扩展标准 `chrome.i18n`
- 默认语言目录:`public/_locales/zh_CN/messages.json`
- 使用方式:`import { useI18n } from '@/utils/chromeI18n'`
- 翻译键格式:直接 key(如 `timestamp_title`);兼容 `namespace:key.path` 并转换为下划线
- 回退策略:缺失翻译返回 key 本身,并在开发模式下记录 warning
- 限制:`chrome.i18n` 跟随浏览器语言,不能在运行时动态切换语言
### WXT 生成文件