From 47e08f80b3fb1ffa8f8b0fef58cc9994cbcb6a72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= <2712495353@qq.com>
Date: Tue, 30 Jun 2026 21:18:28 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=BB=9F=E4=B8=80=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=E7=BB=84=E4=BB=B6=E7=BB=93=E6=9E=84=EF=BC=8C=E7=AE=80?=
=?UTF-8?q?=E5=8C=96=E7=89=B9=E6=80=A7=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/CODING_STANDARDS.md | 12 ++--
src/components/RouterContainer.tsx | 8 +--
src/config/__tests__/features.lazy.test.ts | 2 +-
src/config/__tests__/features.test.ts | 8 +--
src/config/features.tsx | 66 ++++------------------
5 files changed, 24 insertions(+), 72 deletions(-)
diff --git a/.github/CODING_STANDARDS.md b/.github/CODING_STANDARDS.md
index b19d0a5..dab6b0c 100644
--- a/.github/CODING_STANDARDS.md
+++ b/.github/CODING_STANDARDS.md
@@ -677,7 +677,7 @@ src/pages/StorageCleaner/useStorageCleaner.ts — 页面级 Hook
label: '时间戳转换',
description: '日期与时间戳互转',
defaultVisible: true,
- components: { popup: TimestampPage, sidepanel: TimestampPage, tab: TimestampPage },
+ component: TimestampPage,
}
```
@@ -763,11 +763,11 @@ const [themeMode, setThemeMode, isInitialized] = useStorageState(
Chrome Storage 读取是异步的。项目通过 `localStorage` 快照(键名 `snapshot/{storageKey}`)提供同步初始值,消除首屏闪烁。
-| 模块 | 快照工具 | 防覆盖机制 |
-| ---- | -------- | ---------- |
-| `RouterProvider` | `syncSnapshot.ts` | `canPersistRef`(加载成功后才写入)、`hasUserNavigatedRef`(用户导航后不被 storage 覆盖) |
-| `useStorageState` | `syncSnapshot.ts` | `loadSucceededRef` 或 `userModifiedRef` 为 true 时才写入 |
-| `ThemeModeProvider` | `themeSnapshot.ts` | `hasUserSetMode`(用户切换主题后不被 storage 覆盖) |
+| 模块 | 快照工具 | 防覆盖机制 |
+| ------------------- | ------------------ | ----------------------------------------------------------------------------------------- |
+| `RouterProvider` | `syncSnapshot.ts` | `canPersistRef`(加载成功后才写入)、`hasUserNavigatedRef`(用户导航后不被 storage 覆盖) |
+| `useStorageState` | `syncSnapshot.ts` | `loadSucceededRef` 或 `userModifiedRef` 为 true 时才写入 |
+| `ThemeModeProvider` | `themeSnapshot.ts` | `hasUserSetMode`(用户切换主题后不被 storage 覆盖) |
新增持久化状态时,应遵循相同模式:同步快照作初始 state → 异步加载 storage → 加载成功或用户修改后才允许写入。
diff --git a/src/components/RouterContainer.tsx b/src/components/RouterContainer.tsx
index 53b6002..307da7f 100644
--- a/src/components/RouterContainer.tsx
+++ b/src/components/RouterContainer.tsx
@@ -1,4 +1,4 @@
-import { FEATURES, getEntryPointType } from '@/config/features';
+import { FEATURES } from '@/config/features';
import { useRouter } from '@/providers/RouterProvider';
import { Suspense } from 'react';
import PageErrorBoundary from '@/components/PageErrorBoundary';
@@ -6,8 +6,6 @@ import PageSkeleton from '@/components/PageSkeleton';
import { cn } from '@/lib/utils';
import { AlertTriangle } from 'lucide-react';
-const entryPointType = getEntryPointType();
-
export default function RouterContainer() {
const { currentPage, isLoaded } = useRouter();
@@ -19,7 +17,7 @@ export default function RouterContainer() {
}
const currentFeature = FEATURES.find((f) => f.key === currentPage);
- const MatchedComponent = currentFeature?.components?.[entryPointType];
+ const MatchedComponent = currentFeature?.component;
return (
页面未找到
- 该功能在当前运行环境({entryPointType.toUpperCase()})下不可用或已被移除。
+ 该功能不存在或已被移除。
)}
diff --git a/src/config/__tests__/features.lazy.test.ts b/src/config/__tests__/features.lazy.test.ts
index 6aba224..4556a40 100644
--- a/src/config/__tests__/features.lazy.test.ts
+++ b/src/config/__tests__/features.lazy.test.ts
@@ -72,7 +72,7 @@ describe('features 懒加载', () => {
const { render, waitFor } = await import('@testing-library/react');
const { FEATURES } = await import('@/config/features');
- const DashboardPage = FEATURES.find((f) => f.key === 'dashboard')!.components.popup;
+ const DashboardPage = FEATURES.find((f) => f.key === 'dashboard')!.component;
render(
React.createElement(React.Suspense, { fallback: null }, React.createElement(DashboardPage)),
diff --git a/src/config/__tests__/features.test.ts b/src/config/__tests__/features.test.ts
index 07cdecb..db69010 100644
--- a/src/config/__tests__/features.test.ts
+++ b/src/config/__tests__/features.test.ts
@@ -19,15 +19,13 @@ describe('features', () => {
expect(feature).toHaveProperty('label');
expect(feature).toHaveProperty('description');
expect(feature).toHaveProperty('defaultVisible');
- expect(feature).toHaveProperty('components');
+ expect(feature).toHaveProperty('component');
expect(typeof feature.key).toBe('string');
expect(typeof feature.label).toBe('string');
expect(typeof feature.description).toBe('string');
expect(typeof feature.defaultVisible).toBe('boolean');
- expect(typeof feature.components).toBe('object');
- expect(feature.components).toHaveProperty('popup');
- expect(feature.components).toHaveProperty('sidepanel');
- expect(feature.components).toHaveProperty('tab');
+ expect(feature.component).toBeDefined();
+ expect(['function', 'object']).toContain(typeof feature.component);
if (feature.key !== 'dashboard') {
expect(feature).toHaveProperty('icon');
diff --git a/src/config/features.tsx b/src/config/features.tsx
index d98d397..1ca5594 100644
--- a/src/config/features.tsx
+++ b/src/config/features.tsx
@@ -34,11 +34,7 @@ export interface FeatureConfig {
themeColorKey?: PaletteColorKey;
icon?: ComponentType;
defaultVisible: boolean;
- components: {
- popup: ComponentType;
- sidepanel: ComponentType;
- tab: ComponentType;
- };
+ component: ComponentType;
}
export const FEATURES: FeatureConfig[] = [
@@ -47,11 +43,7 @@ export const FEATURES: FeatureConfig[] = [
label: '仪表盘',
description: '',
defaultVisible: true,
- components: {
- popup: DashboardPage,
- sidepanel: DashboardPage,
- tab: DashboardPage,
- },
+ component: DashboardPage,
},
{
key: 'timestamp',
@@ -60,11 +52,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'primary',
icon: Clock,
defaultVisible: true,
- components: {
- popup: TimestampPage,
- sidepanel: TimestampPage,
- tab: TimestampPage,
- },
+ component: TimestampPage,
},
{
key: 'storageCleaner',
@@ -73,11 +61,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'warning',
icon: Database,
defaultVisible: true,
- components: {
- popup: StorageCleanerPage,
- sidepanel: StorageCleanerPage,
- tab: StorageCleanerPage,
- },
+ component: StorageCleanerPage,
},
{
key: 'qrCode',
@@ -86,11 +70,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'success',
icon: QrCode,
defaultVisible: true,
- components: {
- popup: QrCodePage,
- sidepanel: QrCodePage,
- tab: QrCodePage,
- },
+ component: QrCodePage,
},
{
key: 'textStatistics',
@@ -99,11 +79,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'secondary',
icon: FileText,
defaultVisible: true,
- components: {
- popup: TextStatisticsPage,
- sidepanel: TextStatisticsPage,
- tab: TextStatisticsPage,
- },
+ component: TextStatisticsPage,
},
{
key: 'jwt',
@@ -112,11 +88,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'info',
icon: Key,
defaultVisible: true,
- components: {
- popup: JwtPage,
- sidepanel: JwtPage,
- tab: JwtPage,
- },
+ component: JwtPage,
},
{
key: 'jsonTools',
@@ -125,11 +97,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'primary',
icon: GitCompareArrows,
defaultVisible: true,
- components: {
- popup: JsonToolsPage,
- sidepanel: JsonToolsPage,
- tab: JsonToolsPage,
- },
+ component: JsonToolsPage,
},
{
key: 'base64Converter',
@@ -138,11 +106,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'info',
icon: ArrowLeftRight,
defaultVisible: true,
- components: {
- popup: Base64ConverterPage,
- sidepanel: Base64ConverterPage,
- tab: Base64ConverterPage,
- },
+ component: Base64ConverterPage,
},
{
key: 'rightClickRestorer',
@@ -151,11 +115,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'success',
icon: MousePointerClick,
defaultVisible: true,
- components: {
- popup: RightClickRestorerPage,
- sidepanel: RightClickRestorerPage,
- tab: RightClickRestorerPage,
- },
+ component: RightClickRestorerPage,
},
{
key: 'testDataGenerator',
@@ -164,11 +124,7 @@ export const FEATURES: FeatureConfig[] = [
themeColorKey: 'warning',
icon: FileSpreadsheet,
defaultVisible: true,
- components: {
- popup: TestDataGeneratorPage,
- sidepanel: TestDataGeneratorPage,
- tab: TestDataGeneratorPage,
- },
+ component: TestDataGeneratorPage,
},
];