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, }, ];