From 704ec7289dc87914036bb4c227811b394739e03f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Thu, 21 May 2026 00:34:02 +0800 Subject: [PATCH] =?UTF-8?q?fix(pageHeader):=20=E4=BD=BF=E7=94=A8=20MUI=20?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=E8=89=B2=E6=9B=BF=E4=BB=A3=E7=A1=AC=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E9=A2=9C=E8=89=B2=EF=BC=8C=E6=94=AF=E6=8C=81=E6=9A=97?= =?UTF-8?q?=E8=89=B2=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/PageHeader.tsx | 13 ++++---- components/__tests__/PageHeader.test.tsx | 38 ++++++++++++++++-------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/components/PageHeader.tsx b/components/PageHeader.tsx index f708a9c..13481a1 100644 --- a/components/PageHeader.tsx +++ b/components/PageHeader.tsx @@ -1,4 +1,4 @@ -import { alpha, Box, Stack, SxProps, Theme, Typography } from '@mui/material'; +import { alpha, Box, Stack, SxProps, Theme, Typography, useTheme } from '@mui/material'; import { ReactNode } from 'react'; /** @@ -7,7 +7,7 @@ import { ReactNode } from 'react'; export interface PageHeaderProps { /** 要显示的图标组件 */ icon: ReactNode; - /** 图标的颜色,默认为 '#1976d2'(蓝色) */ + /** 图标的颜色,默认使用主题 primary.main 色 */ iconColor?: string; /** 主标题文本 */ title: string; @@ -53,7 +53,7 @@ export interface PageHeaderProps { */ export default function PageHeader({ icon, - iconColor = '#1976d2', + iconColor, title, subtitle, badge, @@ -62,6 +62,9 @@ export default function PageHeader({ subtitleSx, sx, }: PageHeaderProps) { + const theme = useTheme(); + const resolvedIconColor = iconColor ?? theme.palette.primary.main; + return ( {/* 图标容器 */} @@ -69,8 +72,8 @@ export default function PageHeader({ sx={{ p: 1, borderRadius: 2.5, - bgcolor: alpha(iconColor, 0.1), - color: iconColor, + bgcolor: alpha(resolvedIconColor, 0.1), + color: resolvedIconColor, display: 'flex', ...iconSx, }} diff --git a/components/__tests__/PageHeader.test.tsx b/components/__tests__/PageHeader.test.tsx index a601f24..e567199 100644 --- a/components/__tests__/PageHeader.test.tsx +++ b/components/__tests__/PageHeader.test.tsx @@ -2,8 +2,15 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import AccessTimeIcon from '@mui/icons-material/AccessTime'; import CloseIcon from '@mui/icons-material/Close'; import { render, screen } from '@testing-library/react'; +import { ThemeProvider, createTheme } from '@mui/material/styles'; import PageHeader, { type PageHeaderProps } from '@/components/PageHeader'; +const theme = createTheme(); + +function renderWithTheme(ui: React.ReactElement) { + return render({ui}); +} + describe('PageHeader 组件系统', () => { beforeEach(() => { vi.clearAllMocks(); @@ -22,32 +29,37 @@ describe('PageHeader 组件系统', () => { describe('PageHeader UI 渲染', () => { it('应渲染页面标题栏&副标题', () => { - render(); + renderWithTheme(); expect(screen.getByText('时间戳转换')).toBeInTheDocument(); expect(screen.getByText('Unix 毫秒数转换与格式化')).toBeInTheDocument(); }); it('应渲染图标', () => { - render(); + renderWithTheme(); expect(screen.getByTestId('AccessTimeIcon')).toBeInTheDocument(); }); it('应渲染自定义图标&图标颜色', () => { - render(} iconColor="#FF0000" />); + renderWithTheme(} iconColor="#FF0000" />); expect(screen.getByTestId('CloseIcon')).toBeInTheDocument(); expect(screen.getByTestId('CloseIcon')).toHaveStyle('color: #FF0000;'); }); + it('应默认使用主题 primary 色', () => { + renderWithTheme(} />); + expect(screen.getByTestId('CloseIcon')).toHaveStyle(`color: ${theme.palette.primary.main};`); + }); + it('应渲染 badge 组件', () => { const badge = New; - render(); + renderWithTheme(); expect(screen.getByTestId('test-badge')).toBeInTheDocument(); expect(screen.getByText('New')).toBeInTheDocument(); }); it('应渲染 badge 与 title 并排布局', () => { const badge = v1.0; - render(); + renderWithTheme(); const title = screen.getByText('时间戳转换'); const badgeEl = screen.getByTestId('side-badge'); expect(title).toBeInTheDocument(); @@ -57,13 +69,15 @@ describe('PageHeader 组件系统', () => { describe('PageHeader 条件渲染', () => { it('subtitle 为 undefined 时不应渲染副标题', () => { - const { container } = render(} title="仅标题" />); + const { container } = renderWithTheme( + } title="仅标题" />, + ); const captionElements = container.querySelectorAll('p'); expect(captionElements.length).toBe(0); }); it('subtitle 为空字符串时不应渲染副标题', () => { - const { container } = render( + const { container } = renderWithTheme( } title="标题" subtitle="" />, ); const captionElements = container.querySelectorAll('p'); @@ -71,14 +85,14 @@ describe('PageHeader 组件系统', () => { }); it('badge 为 undefined 时不应渲染 badge 区域', () => { - render(); + renderWithTheme(); expect(screen.queryByText('v1.0')).not.toBeInTheDocument(); }); }); describe('PageHeader 样式扩展', () => { it('iconSx 应作为属性传递给图标容器', () => { - const { container } = render( + const { container } = renderWithTheme( , ); const iconContainer = container.querySelector('div'); @@ -86,19 +100,19 @@ describe('PageHeader 组件系统', () => { }); it('titleSx 应作为属性传递给标题', () => { - render(); + renderWithTheme(); const titleEl = screen.getByText('时间戳转换'); expect(titleEl).toBeInTheDocument(); }); it('subtitleSx 应作为属性传递给副标题', () => { - render(); + renderWithTheme(); const subtitleEl = screen.getByText('Unix 毫秒数转换与格式化'); expect(subtitleEl).toBeInTheDocument(); }); it('sx 应作为属性传递给外层容器', () => { - const { container } = render(); + const { container } = renderWithTheme(); const outerElement = container.firstChild; expect(outerElement).toBeTruthy(); });