Merge remote-tracking branch 'origin/main' into develop

This commit is contained in:
雨霖铃
2026-05-28 22:35:39 +08:00
14 changed files with 753 additions and 53 deletions
+24
View File
@@ -0,0 +1,24 @@
# src/
源码目录,存放全局样式定义。
## 文件说明
| 文件 | 用途 |
| ----------- | ----------------- |
| `index.css` | 全局 CSS 入口文件 |
## index.css
全局样式入口,包含:
- **Tailwind 指令**`@tailwind base/components/utilities`
- **shadcn/ui CSS 变量**:定义 `--background``--primary``--destructive``--card``--muted``--accent``--border``--ring` 等语义化颜色变量
- **主题色值**`:root`(亮色)和 `.dark`(暗色)两套完整的颜色定义
- **圆角变量**`--radius` 定义全局圆角大小
## 修改注意事项
- 修改 CSS 变量会影响所有使用 shadcn/ui 语义化 token 的组件
- 新增颜色变量需同时在 `:root``.dark` 中定义
- 避免在组件中硬编码颜色值,应使用 CSS 变量或 Tailwind 的语义化类名
+27
View File
@@ -0,0 +1,27 @@
# components/
通用业务组件目录,存放跨页面复用的 UI 组件,与具体工具页面解耦。
## 组件列表
| 组件 | 用途 |
| ----------------------- | ------------------------------------------------------------------------------ |
| `TopBar.tsx` | 顶部导航栏,集成搜索(含历史记录)、主题切换、语言切换、返回导航 |
| `RouterContainer.tsx` | 路由容器,根据当前路由动态渲染对应页面组件,集成错误边界和骨架屏 |
| `SwitchButtonGroup.tsx` | 通用切换按钮组,支持 `small/medium/large` 三种尺寸,用于页面子模式切换 |
| `TextInputArea.tsx` | 增强文本输入区域,支持校验规则、工具栏操作、字符计数、清空 |
| `CopyButton.tsx` | 一键复制按钮,支持复制成功状态动画,封装 `copyTextToClipboard``toast` 反馈 |
| `ImageUploader.tsx` | 图片上传组件,支持拖拽上传、文件选择和预览 |
| `QrCodePreview.tsx` | 二维码预览组件,展示生成的二维码图片,提供复制和下载操作 |
| `DecodeResultPaper.tsx` | Base64 解码结果展示面板,显示 MIME 类型、文件大小、文件名输入和下载按钮 |
| `GlobalSnackbar.tsx` | 全局消息提示组件 + Context Provider,支持受控/Hook/全局单例三种使用方式 |
| `ErrorBoundary.tsx` | 全局错误边界(类组件),捕获子组件树 JS 错误并展示友好错误页面 |
| `PageErrorBoundary.tsx` | 页面级错误边界,适配 shadcn 暗黑模式,支持 `resetKey` 自动恢复 |
| `PageSkeleton.tsx` | 页面骨架屏,提供 `dashboard``tool` 两种变体,用于 Suspense fallback |
## 使用约定
- 优先使用 `components/ui/` 下的 shadcn/ui 基础组件
- 组件使用 `cn()` 合并 Tailwind 类名,支持 `className` 透传
- 需要 memo 优化的组件使用 `React.memo` + `displayName`
- 需要 ref 转发的组件使用 `React.forwardRef` + `displayName`
+40
View File
@@ -0,0 +1,40 @@
# components/ui/
shadcn/ui 基础原子组件目录,基于 Radix UI 原语 + Tailwind CSS 实现。
## 组件列表
| 组件 | 用途 |
| -------------- | -------------------------------------------------------------------------------------------------- |
| `button.tsx` | 按钮组件,支持 `default/destructive/outline/secondary/ghost/link` 变体和 `default/sm/lg/icon` 尺寸 |
| `input.tsx` | 标准输入框,统一的 ring/focus 样式 |
| `select.tsx` | 下拉选择组件,包含 Trigger、Content、Item 等子组件 |
| `dialog.tsx` | 对话框组件,包含 Overlay、Content、Header、Footer、Title、Description |
| `checkbox.tsx` | 复选框组件 |
| `label.tsx` | 标签组件 |
| `switch.tsx` | 开关组件 |
| `badge.tsx` | 徽章组件,支持 `default/secondary/destructive/outline` 变体 |
## 使用方式
```tsx
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
```
## 添加新组件
使用 shadcn/ui CLI 添加新组件:
```bash
npx shadcn-ui@latest add <component-name>
```
组件配置在项目根目录的 `components.json` 中定义。
+44
View File
@@ -0,0 +1,44 @@
# config/
应用级配置目录,存放功能特性的注册中心。
## 文件说明
| 文件 | 用途 |
| -------------- | ---------------------------------------- |
| `features.tsx` | 核心配置文件,定义所有工具功能的注册信息 |
## features.tsx
`FEATURES` 数组是路由和功能元数据的**单一事实来源**,每个功能定义包含:
- `key`:页面类型标识(`PageType`
- `labelKey` / `descriptionKey`i18n 翻译键
- `themeColorKey`:主题色(`primary/success/warning/error/secondary/info`
- `icon`lucide-react 图标组件
- `defaultVisible`:默认是否可见
- `components`:三种渲染模式的懒加载组件(`popup``sidepanel``tab`
## 已注册功能(11 个)
| key | 图标 | 说明 |
| -------------------- | ----------------- | ----------------- |
| `dashboard` | — | 仪表盘首页 |
| `timestamp` | Clock | 时间戳转换工具 |
| `storageCleaner` | Database | 存储清理工具 |
| `qrCode` | QrCode | 二维码工具 |
| `textStatistics` | FileText | 文本统计工具 |
| `jwt` | Key | JWT 解析工具 |
| `jsonDiff` | GitCompareArrows | JSON 差异比较工具 |
| `base64Converter` | ArrowLeftRight | Base64 转换器 |
| `markdownToHtml` | Code | Markdown 转 HTML |
| `htmlToMarkdown` | File | HTML 转 Markdown |
| `rightClickRestorer` | MousePointerClick | 右键菜单恢复工具 |
## 导出函数
- `getFeatureByKey(key)` — 根据 key 获取功能配置
- `getDefaultVisibleFeatureKeys()` — 获取默认可见的功能 key 列表
- `getAllFeatureKeys()` — 获取所有功能 key 列表
- `getDefaultPageOrder()` — 获取默认页面排序(不含 dashboard)
- `getEntryPointType()` — 判断当前入口类型(popup/sidepanel/tab
+51
View File
@@ -0,0 +1,51 @@
# entrypoints/
WXT 框架要求的扩展生命周期入口点,对应 Chrome Extension 的各个上下文。
## 入口文件
| 文件 | 用途 |
| ------------------------------- | --------------------------------------------------------------------------------------------- |
| `background.ts` | Service Worker 入口:注册右键菜单、监听菜单点击、处理消息通信、管理侧边栏状态、注入主环境脚本 |
| `content.ts` | Content Script 入口:注入所有页面(`<all_urls>`),在 `document_end` 时初始化消息处理器 |
| `rightClickRestorer.content.ts` | 专用 Content Script:处理右键菜单恢复功能,注入浮动状态徽章 |
## 子目录
### popup/
Popup 弹窗页面(点击扩展图标弹出)。
| 文件 | 用途 |
| ------------ | ------------------------------------------------------------------------------ |
| `index.html` | HTML 入口 |
| `main.tsx` | React 挂载点 |
| `App.tsx` | 根组件,组装 `RouterProvider` + `TopBar` + `ErrorBoundary` + `RouterContainer` |
### sidepanel/
侧边栏页面,结构与 popup 类似,额外通知 background 侧边栏开启/关闭状态。
### options/
设置页面,支持:
- 拖拽排序功能顺序(`@dnd-kit`
- 功能可见性管理(显示/隐藏)
- Popup/Sidepanel/Tab 三种模式独立配置
### content/
Content Script 内部分模块:
| 文件 | 用途 |
| ----------------------- | ------------------------------------------------------------------- |
| `messageHandler.ts` | 消息处理器初始化入口 |
| `contextMenuHandler.ts` | 右键菜单点击事件处理,执行时间戳转换/文本统计并通过 UI Popover 展示 |
| `uiPopover.ts` | 在页面中注入浮层 Popover UI,展示右键菜单操作结果 |
## 架构说明
- `background.ts` 是扩展的核心协调者,处理跨上下文通信
- `content.ts` 注入到所有页面,负责接收和处理来自 background 的消息
- `popup/``sidepanel/``options/` 共享同一套页面组件(来自 `pages/`),通过 `RouterProvider` 的不同配置实现独立路由
+26
View File
@@ -0,0 +1,26 @@
# lib/
通用库工具目录,存放与业务无关的底层工具函数。
## 文件说明
| 文件 | 用途 |
| ---------- | ------------------------------------ |
| `utils.ts` | `cn()` 函数 — shadcn/ui 标准工具函数 |
## cn()
组合 `clsx` + `tailwind-merge`,用于合并和去重 Tailwind CSS 类名:
```typescript
import { cn } from '@/lib/utils';
// 条件类名 + 合并外部 className
<div className={cn(
'flex items-center gap-3 px-3',
isActive && 'bg-primary text-primary-foreground',
className,
)}>
```
所有需要动态合并 Tailwind 类名的场景都应使用 `cn()`,而非手动拼接字符串。
+140
View File
@@ -0,0 +1,140 @@
# pages/
功能页面组件目录,每个子目录对应一个工具页面。
## 目录结构约定
典型页面遵循 **UI + Hook 分离** 模式:
```
pages/FeatureName/
├── index.tsx # 页面 UI(纯展示,使用 shadcn/ui 组件)
├── useFeatureName.ts # 业务逻辑 Hook(状态管理 + 转换逻辑)
├── constants.ts # 常量定义(可选)
├── SubComponent.tsx # 子组件(可选)
└── __tests__/ # 测试文件
└── index.test.tsx
```
## 页面列表
### Dashboard/
仪表盘首页,以卡片网格展示所有可见工具,支持点击导航。
| 文件 | 用途 |
| -------------- | -------------------------------------------- |
| `index.tsx` | 页面组件,渲染工具卡片网格 |
| `ToolCard.tsx` | 工具卡片组件,展示图标、标题、描述和实时数据 |
### Timestamp/
时间戳转换工具,支持秒/毫秒级互转、多时区选择、实时时钟。
| 文件 | 用途 |
| -------------------------- | ----------------------------------------------------------------- |
| `index.tsx` | 页面 UI |
| `useTimestampConverter.ts` | 业务逻辑 Hook,包含转换模式、输入、单位、时区状态和响应式计算管线 |
| `LiveClock.tsx` | 实时时钟子组件,`React.memo` 优化 |
| `ResultView.tsx` | 转换结果展示子组件 |
| `constants.ts` | 时区列表等常量 |
### StorageCleaner/
浏览器存储清理工具,支持 Cookie/LocalStorage/SessionStorage/IndexedDB/Cache/SW 清理。
| 文件 | 用途 |
| --------------------------- | -------------- |
| `index.tsx` | 页面 UI |
| `useStorageCleaner.ts` | 业务逻辑 Hook |
| `StorageOptionsGrid.tsx` | 清理选项网格 |
| `StorageCleanerConfirm.tsx` | 清理确认对话框 |
| `AutoRefreshToggle.tsx` | 自动刷新开关 |
| `ErrorDisplay.tsx` | 错误展示组件 |
| `CleaningResult.tsx` | 清理结果展示 |
| `OptionItem.tsx` | 单个选项组件 |
### QrCode/
二维码工具,支持生成(URL→QR)和解析(QR→URL)。
| 文件/目录 | 用途 |
| ------------- | ---------------- |
| `index.tsx` | 页面 UI |
| `types.ts` | 类型定义 |
| `contexts/` | Context Provider |
| `hooks/` | 业务逻辑 Hooks |
| `components/` | 子组件 |
### TextStatistics/
文本统计工具,实时计算字符数、单词数、行数、字节大小。
| 文件 | 用途 |
| ----------- | --------------------------------------------- |
| `index.tsx` | 页面组件,集成 `TextInputArea` 和统计结果展示 |
### Jwt/
JWT 解析工具,解码 Header/Payload/Signature。
| 文件/目录 | 用途 |
| ------------- | ---------------- |
| `index.tsx` | 页面 UI |
| `types.ts` | 类型定义 |
| `contexts/` | Context Provider |
| `hooks/` | 业务逻辑 Hooks |
| `components/` | 子组件 |
### JsonTools/
JSON 工具集:差异比较、格式化、YAML/TOML/Minify 转换。
| 文件 | 用途 |
| ------------------------ | ---------------------------- |
| `index.tsx` | 页面入口,子模式切换 |
| `types.ts` | 类型定义 |
| `diffEngine.ts` | 差异比较引擎 |
| `JsonDiffInput.tsx` | JSON 输入组件 |
| `DiffResult.tsx` | 差异结果展示 |
| `DiffNavigator.tsx` | 差异导航器 |
| `JsonFormatSection.tsx` | 格式化区域 |
| `JsonConvertSection.tsx` | 转换区域(YAML/TOML/Minify |
| `JsonTree.tsx` | JSON 树形展示 |
### Base64Converter/
Base64 编解码工具,支持文本/文件/图片三种模式。
| 文件 | 用途 |
| ---------------------------- | --------------------- |
| `index.tsx` | 页面入口,子模式切换 |
| `useBase64Converter.ts` | 业务逻辑 Hook |
| `TextMode.tsx` | 文本模式 |
| `Base64ConverterSection.tsx` | 文件/图片通用转换区域 |
### MarkdownToHtml/
Markdown 转 HTML 工具,支持分栏/预览/源码三种视图模式。
### HtmlToMarkdown/
HTML 转 Markdown 工具,支持分栏/预览/Markdown 三种视图模式。
### RightClickRestorer/
右键菜单恢复工具,解除网站对右键的限制。
| 文件 | 用途 |
| -------------------------- | ------------- |
| `index.tsx` | 页面 UI |
| `useRightClickRestorer.ts` | 业务逻辑 Hook |
## 新增页面
1.`types/storage.d.ts` 添加 `PageType` 联合类型成员
2.`config/features.tsx``FEATURES` 数组添加配置
3.`pages/` 创建页面目录(遵循上述结构)
4.`i18n/locales/{zh,en}/features.json` 添加翻译
5. 如需新权限,更新 `wxt.config.ts`
6. 添加对应的单元测试
+63
View File
@@ -0,0 +1,63 @@
# providers/
React Context Provider 目录,为整个应用提供全局共享状态。
## 文件说明
| 文件 | 用途 |
| ----------------------- | ---------------------- |
| `AppRoot.tsx` | 应用根 Provider 组合器 |
| `RouterProvider.tsx` | 路由 Context Provider |
| `ThemeModeProvider.tsx` | 主题模式 Provider |
## AppRoot.tsx
应用根 Provider 组合器,按顺序包裹:
```
React.StrictMode
└── ThemeModeProvider
└── RouterProvider
└── children
```
## RouterProvider.tsx
路由 Context Provider,管理:
- **当前页面**`currentPage``PageType`
- **可见页面列表**`visiblePages`
- **页面排序**`pageOrder`
- **加载状态**`isLoaded`
核心特性:
- 通过 `chrome.storage` 持久化路由状态
- 使用 `localStorage` 快照实现首屏 0 闪烁
- 支持 popup/sidepanel/tab 三种入口的独立路由同步(通过 `syncKey``visiblePagesKey``pageOrderKey` 配置)
- 处理右键菜单待处理数据的路由跳转
- 监听 `chrome.storage.onChanged` 实现跨端同步
导出:
- `RouterProvider` 组件
- `useRouter()` Hook — 获取 `currentPage``visiblePages``pageOrder``navigateTo``goBack`
## ThemeModeProvider.tsx
主题模式 Provider,管理:
- **主题模式**`light` / `dark` / `system`
- **解析后的主题**`resolvedTheme``light` / `dark`
核心特性:
- 使用 `localStorage` 快照实现首屏 0 闪烁
- 监听系统级暗色模式变化(`matchMedia`
- 通过 `chrome.storage` 跨端同步主题偏好
- 自动在 `document.documentElement` 上切换 `dark` class
导出:
- `ThemeModeProvider` 组件
- `useThemeMode()` Hook — 获取 `themeMode``resolvedTheme``setThemeMode`
+42
View File
@@ -0,0 +1,42 @@
# types/
全局共享的 TypeScript 类型声明文件目录。
## 文件说明
### storage.d.ts
核心类型定义文件,包含:
**页面类型:**
- `PageType` — 所有页面类型的联合类型(`dashboard` | `timestamp` | `storageCleaner` | ...
- `JsonToolsPageMode` — JSON 工具子模式(`diff` | `format` | `yaml` | `toml` | `minify`
- `Base64ConverterPageMode` — Base64 子模式(`text` | `file` | `image`
- `Base64ConvertDirection` — 编解码方向(`encode` | `decode`
- `MarkdownToHtmlPreviewMode` — Markdown 预览模式(`split` | `preview` | `html`
- `HtmlToMarkdownPreviewMode` — HTML 预览模式(`split` | `preview` | `markdown`
**存储 Schema**
- `StorageSchema` — Chrome Storage 完整数据结构定义,所有存储键必须在此声明
- 键名使用 kebab-case 格式(如 `app/currentRoute`
- 包含路由、主题、工具偏好、搜索历史等所有持久化数据
**其他类型:**
- `FormMapEntry` — 表单映射条目定义
- `ContextMenuPendingData` — 右键菜单待处理数据
- `StorageCleanerPreferences` / `StorageCleanerOptions` — 存储清理偏好
- `CleaningResult` / `StorageCleanResult` — 清理结果类型
### qrious.d.ts
`qrious` 库的类型声明,定义 QR 码生成选项和 `QRious` 类。
## 修改 StorageSchema 的注意事项
修改 `StorageSchema` 时,必须:
1.`utils/chromeStorage.ts` 添加版本迁移函数
2. 在测试中覆盖迁移场景
+42
View File
@@ -0,0 +1,42 @@
# utils/
通用工具函数和 React 自定义 Hooks 目录,与具体页面解耦。
## 工具函数
| 文件 | 用途 |
| -------------------- | --------------------------------------------------------------------------------------------------- |
| `chromeStorage.ts` | Chrome Storage API 封装:类型安全的 `StorageUtils` 类,提供 `get/set/remove` 方法 |
| `chromeTabs.ts` | Chrome Tabs API 封装:获取活动标签页、获取域名、在新标签页打开扩展页面 |
| `clipboard.ts` | 剪贴板操作:`copyTextToClipboard`(文本)、`copyImageToClipboard`(图片) |
| `messages.ts` | 扩展消息通信:基于 `@webext-core/messaging`,定义 `MessageAction` 枚举和 `ProtocolMap` 类型安全映射 |
| `contextMenu.ts` | 右键菜单配置与操作:定义菜单项、创建菜单、解析点击事件、ID→PageType 映射 |
| `base64Converter.ts` | Base64 编解码:文本↔Base64、文件↔Base64、图片预览,定义文件大小限制和图像 MIME 类型 |
| `jwt.ts` | JWT 解析:Base64URL 解码、解析 Header/Payload/Signature、JSON 格式化输出 |
| `jsonFormatter.ts` | JSON 格式化/压缩:支持缩进、按键排序、minify |
| `jsonToYaml.ts` | JSON→YAML 转换 |
| `jsonToToml.ts` | JSON→TOML 转换 |
| `markdownToHtml.ts` | Markdown→HTML 转换:基于 `marked` 库,支持 GFM 和换行转换 |
| `htmlToMarkdown.ts` | HTML→Markdown 转换:基于 DOMParser 解析 |
| `qrCodeParser.ts` | 二维码解析:基于 `qr-scanner` 库从文件中解析二维码 |
| `storageCleaner.ts` | 存储清理:获取当前标签页、检测受限 URL、计算 Cookie/Storage 大小、清理操作 |
| `textStatistics.ts` | 文本统计:使用 `Intl.Segmenter` 计算字符数/单词数/行数/字节大小 |
| `format.ts` | 通用格式化:`formatBytes` 将字节转为可读字符串(B/KB/MB/GB/TB |
| `dayjs.ts` | Day.js 初始化:扩展 UTC、Timezone、RelativeTime 插件,加载中文本地化 |
## 自定义 Hooks
| 文件 | 用途 |
| ----------------------- | -------------------------------------------------------------------------------------------------------------- |
| `useStorageState.ts` | Chrome Storage 状态 Hook:类似 `useState`,值自动同步到 `chrome.storage`,使用 `localStorage` 快照消除首屏闪烁 |
| `useLazyTranslation.ts` | 懒加载翻译 Hook:按需动态导入 i18n 命名空间,支持预加载和缓存 |
| `useContextMenuData.ts` | 右键菜单数据 Hook:从 storage 读取待处理数据,匹配 featureKey 后消费并触发回调 |
| `useDebounce.ts` | 防抖 Hook:对值进行延迟更新,避免频繁触发 |
## 使用约定
- 工具函数使用**命名导出**`export function xxx()`
- 工具函数**不抛异常**,返回包含 `hasError``error` 字段的结果对象
- Hook 使用 `use` 前缀命名,定义返回值接口类型
- 存储操作使用 `chromeStorage.ts``storageUtil` 封装,不要直接调用 `chrome.storage`
- 消息通信使用 `messages.ts``sendMessage`/`onMessage`,不要使用原生 `chrome.runtime.sendMessage`