From df3eee87498000c6399b7c75aa607df634c7286f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Sat, 23 May 2026 13:15:25 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E6=89=80?= =?UTF-8?q?=E6=9C=89=E9=A1=B5=E9=9D=A2=E7=9A=84=20PageHeader=20=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除 PageHeader 组件及其测试文件,清理相关不再使用的导入和变量。 --- components/PageHeader.tsx | 104 ----------------------- components/__tests__/PageHeader.test.tsx | 100 ---------------------- entrypoints/options/App.tsx | 9 +- pages/Base64Converter/index.tsx | 17 ---- pages/HtmlToMarkdown/index.tsx | 9 +- pages/JsonTools/index.tsx | 28 +----- pages/Jwt/index.tsx | 8 -- pages/MarkdownToHtml/index.tsx | 10 +-- pages/QrCode/index.tsx | 11 --- pages/TextStatistics/index.tsx | 10 --- pages/Timestamp/index.tsx | 9 -- 11 files changed, 4 insertions(+), 311 deletions(-) delete mode 100644 components/PageHeader.tsx delete mode 100644 components/__tests__/PageHeader.test.tsx diff --git a/components/PageHeader.tsx b/components/PageHeader.tsx deleted file mode 100644 index 3bd9fac..0000000 --- a/components/PageHeader.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { ReactNode, useMemo } from 'react'; -import { getEntryPointType } from '@/config/features'; -import { cn } from '@/lib/utils'; // shadcn 核心类名合并工具 - -export interface PageHeaderProps extends React.HTMLAttributes { - /** 要显示的图标组件 */ - icon: ReactNode; - /** - * 图标的颜色,支持: - * 1. Tailwind 颜色类名 (如 'text-blue-500', 'text-primary') -> 推荐 - * 2. 原生颜色值 (如 '#3b82f6') - */ - iconColor?: string; - /** 主标题文本 */ - title: string; - /** 副标题文本(可选) */ - subtitle?: string; - /** 在标题右侧显示的徽章/标签组件(可选) */ - badge?: ReactNode; - /** 覆盖图标容器的类名 */ - iconClassName?: string; - /** 覆盖主标题的类名 */ - titleClassName?: string; - /** 覆盖副标题的类名 */ - subtitleClassName?: string; -} - -export default function PageHeader({ - icon, - iconColor = 'text-blue-500', // 默认改用类名,若需保持 Hex 可写 "#3b82f6" - title, - subtitle, - badge, - iconClassName, - titleClassName, - subtitleClassName, - className, - ...props -}: PageHeaderProps) { - const entryPointType = useMemo(() => getEntryPointType(), []); - - // 扩展环境判断:如果是 popup 形式则不渲染头部 - if (entryPointType === 'popup') { - return null; - } - - // 判断传入的是否是 Hex/RGB 等原生颜色值 - const isRawColor = - iconColor.startsWith('#') || iconColor.startsWith('rgb') || iconColor.startsWith('hsl'); - - return ( -
- {/* 图标容器 */} -
- {/* 确保图标大小可控,通过子元素选择器约束 SVG 宽高 */} -
{icon}
-
- - {/* 标题区域 */} -
- {/* 标题行(含徽章) */} -
-

- {title} -

- {badge &&
{badge}
} -
- - {/* 副标题 - 使用 p 标签(block)保证换行 */} - {subtitle && ( -

- {subtitle} -

- )} -
-
- ); -} diff --git a/components/__tests__/PageHeader.test.tsx b/components/__tests__/PageHeader.test.tsx deleted file mode 100644 index 0b4a8f0..0000000 --- a/components/__tests__/PageHeader.test.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { render, screen } from '@testing-library/react'; -import PageHeader, { type PageHeaderProps } from '@/components/PageHeader'; - -vi.mock('@/config/features', () => ({ - getEntryPointType: vi.fn(() => 'sidepanel'), -})); - -describe('PageHeader 组件系统', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - afterEach(() => { - vi.restoreAllMocks(); - vi.resetAllMocks(); - }); - - const defaultProps: PageHeaderProps = { - icon: , - title: '时间戳转换', - subtitle: 'Unix 毫秒数转换与格式化', - }; - - describe('PageHeader UI 渲染', () => { - it('应渲染页面标题栏&副标题', () => { - render(); - expect(screen.getByText('时间戳转换')).toBeInTheDocument(); - expect(screen.getByText('Unix 毫秒数转换与格式化')).toBeInTheDocument(); - }); - - it('应渲染图标', () => { - render(); - expect(screen.getByTestId('test-icon')).toBeInTheDocument(); - }); - - it('应渲染自定义图标&图标颜色', () => { - render( - X} - iconColor="#FF0000" - />, - ); - expect(screen.getByTestId('custom-icon')).toBeInTheDocument(); - }); - - it('应默认使用蓝色作为 primary 色', () => { - render(); - const iconContainer = screen.getByTestId('test-icon').parentElement?.parentElement; - expect(iconContainer).toHaveClass('text-blue-500'); - }); - - it('应渲染 badge 组件', () => { - const badge = New; - render(); - expect(screen.getByTestId('test-badge')).toBeInTheDocument(); - }); - - it('应支持自定义 iconClassName', () => { - render(); - const iconContainer = screen.getByTestId('test-icon').parentElement?.parentElement; - expect(iconContainer).toHaveClass('custom-icon-class'); - }); - - it('应支持自定义 titleClassName', () => { - render(); - const title = screen.getByText('时间戳转换'); - expect(title).toHaveClass('custom-title-class'); - }); - - it('应支持自定义 subtitleClassName', () => { - render(); - const subtitle = screen.getByText('Unix 毫秒数转换与格式化'); - expect(subtitle).toHaveClass('custom-subtitle-class'); - }); - - it('应支持自定义 className', () => { - const { container } = render(); - const outerElement = container.firstChild; - expect(outerElement).toHaveClass('custom-page-header'); - }); - - it('无副标题时不渲染副标题区域', () => { - const { container } = render(); - const subtitles = container.querySelectorAll('.text-muted-foreground'); - expect(subtitles.length).toBe(0); - }); - }); - - describe('PageHeader 入口点隐藏', () => { - it('popup 模式下应返回 null', async () => { - const { getEntryPointType } = await import('@/config/features'); - vi.mocked(getEntryPointType).mockReturnValue('popup'); - - const { container } = render(); - expect(container.innerHTML).toBe(''); - }); - }); -}); diff --git a/entrypoints/options/App.tsx b/entrypoints/options/App.tsx index 121eeb9..346be9f 100644 --- a/entrypoints/options/App.tsx +++ b/entrypoints/options/App.tsx @@ -1,5 +1,5 @@ import { SyntheticEvent, useEffect, useMemo, useState } from 'react'; -import { GripVertical, RefreshCw, Settings } from 'lucide-react'; +import { GripVertical, RefreshCw } from 'lucide-react'; import { closestCenter, DndContext, @@ -28,7 +28,6 @@ import { } from '@/config/features'; import GlobalSnackbar, { useSnackbarState } from '@/components/GlobalSnackbar'; import PageErrorBoundary from '@/components/PageErrorBoundary'; -import PageHeader from '@/components/PageHeader'; import { useTranslation } from 'react-i18next'; const PALETTE_COLORS: Record = { @@ -317,12 +316,6 @@ export default function App() { {/* 顶部标题与导航栏 */}
- } - iconColor="#1976d2" - title="应用设置" - subtitle="针对不同窗口类型独立配置 Dashboard 中显示的功能及其排序" - /> {/* Tab 与恢复按钮同行 */}
diff --git a/pages/Base64Converter/index.tsx b/pages/Base64Converter/index.tsx index a32df20..5b53d44 100644 --- a/pages/Base64Converter/index.tsx +++ b/pages/Base64Converter/index.tsx @@ -1,7 +1,4 @@ -import { Image as ImageIcon, Type, Upload } from 'lucide-react'; import { useLazyTranslation } from '@/utils/useLazyTranslation'; -import PageHeader from '@/components/PageHeader'; - import { useStorageState } from '@/utils/useStorageState'; import type { Base64ConverterPageMode } from '@/types/storage'; import TextMode from './TextMode'; @@ -22,22 +19,8 @@ export default function Index() { isValidPageMode, ); - const modeIcon: Record = { - text: , - file: , - image: , - }; - return (
- - - } - /> -
{/* 工具栏集成区 */}
diff --git a/pages/JsonTools/index.tsx b/pages/JsonTools/index.tsx index c8ba24a..e808363 100644 --- a/pages/JsonTools/index.tsx +++ b/pages/JsonTools/index.tsx @@ -1,7 +1,5 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { ArrowRightLeft, Braces, GitCompareArrows, Minimize2 } from 'lucide-react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useLazyTranslation } from '@/utils/useLazyTranslation'; -import PageHeader from '@/components/PageHeader'; import JsonDiffInput from './JsonDiffInput'; import DiffResult from './DiffResult'; import DiffNavigator from './DiffNavigator'; @@ -99,22 +97,6 @@ export default function Index() { const activePath = diffResult && total > 0 ? diffResult.diffPaths[currentDiffIndex] : undefined; - const modeTitles: Record = { - diff: { title: 'jsonDiff:pageTitle', subtitle: 'jsonDiff:pageSubtitle' }, - format: { title: 'jsonFormat:formatTitle', subtitle: 'jsonFormat:formatSubtitle' }, - yaml: { title: 'jsonFormat:yamlTitle', subtitle: 'jsonFormat:yamlSubtitle' }, - toml: { title: 'jsonFormat:tomlTitle', subtitle: 'jsonFormat:tomlSubtitle' }, - minify: { title: 'jsonFormat:minifyTitle', subtitle: 'jsonFormat:minifySubtitle' }, - }; - - const modeIcon: Record = { - diff: , - format: , - yaml: , - toml: , - minify: , - }; - const yamlConvert: ConvertFunction = useCallback((text: string) => { const r = jsonToYaml(text); return { output: r.output, originalBytes: r.originalBytes, outputBytes: r.outputBytes }; @@ -132,14 +114,6 @@ export default function Index() { return (
- - setPageMode(v)} diff --git a/pages/Jwt/index.tsx b/pages/Jwt/index.tsx index b79ca9f..189c0c7 100644 --- a/pages/Jwt/index.tsx +++ b/pages/Jwt/index.tsx @@ -1,6 +1,4 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; -import { Key } from 'lucide-react'; -import PageHeader from '@/components/PageHeader'; import { parseJwt, stringifyJson } from '@/utils/jwt'; import CopyButton from '@/components/CopyButton'; import TextInputArea from '@/components/TextInputArea'; @@ -73,12 +71,6 @@ export default function Index() { return (
- } // 💡 规范锁死 Icon 宽高,抹杀闪烁 - /> -
{/* 输入终端 */} - } - className="pb-1" - /> -
{/* 工具集成控制中枢 */}
diff --git a/pages/QrCode/index.tsx b/pages/QrCode/index.tsx index 4ba1542..cd2713b 100644 --- a/pages/QrCode/index.tsx +++ b/pages/QrCode/index.tsx @@ -1,5 +1,3 @@ -import { QrCode as QrCodeIcon } from 'lucide-react'; // 💡 别名规整,防止与页面组件发生重名误判 -import PageHeader from '@/components/PageHeader'; import SwitchButtonGroup from '@/components/SwitchButtonGroup'; import { useLazyTranslation } from '@/utils/useLazyTranslation'; @@ -26,15 +24,6 @@ export default function Index() { - 替换为标准的 p-4 呼吸内边距配合 flex flex-col space-y-4,接管系统级重排! */}
- {/* 标题控制栏:追加微调 py-0.5,防范文字边缘截断 */} - } // 💡 规范对齐:强制锁死 Icon 宽高,抹杀闪烁 - iconColor="text-green-700" - className="pb-1" - /> - {/* 流式中央控制切流卡:注入 sm 断点防御,防范单栏状态下发生变形 */}
- {/* 头部区域 */} - } - iconColor="text-purple-500" - /> - {/* 文本输入区域 */}
- {/* Header */} - } - /> - {/* 动态参考信息时钟条 */}