casualroom/apps/fenghuo/web/components/site-header.tsx

105 lines
2.8 KiB
TypeScript
Executable File

'use client';
import { Separator } from '@nice/ui/components/separator';
import { SidebarTrigger } from '@nice/ui/components/sidebar';
import { IconCalendar } from '@tabler/icons-react';
import { cn } from '@nice/ui/lib/utils';
import { useState, useEffect } from 'react';
import { useDashboard } from './providers/dashboard-provider';
// 页面信息接口
export interface PageInfo {
title: string;
subtitle?: string;
rightContent?: React.ReactNode;
}
// 组件属性接口
export interface SiteHeaderProps {
pageInfo?: PageInfo;
showDate?: boolean;
rightContent?: React.ReactNode;
className?: string;
useContext?: boolean; // 新增:是否使用 context 中的页面信息
}
// 格式化日期
const formatDate = (date: Date) => {
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
};
// 默认时间显示组件
const DefaultTimeDisplay = () => {
const [currentDate, setCurrentDate] = useState<Date | null>(null);
useEffect(() => {
// 只在客户端设置当前时间
setCurrentDate(new Date());
}, []);
// 在水合完成之前显示占位符
if (!currentDate) {
return (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<IconCalendar className="h-4 w-4" />
<time>...</time>
</div>
);
}
return (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<IconCalendar className="h-4 w-4" />
<time dateTime={currentDate.toISOString()}>{formatDate(currentDate)}</time>
</div>
);
};
// 页面标题区域组件
const PageTitleSection = ({ pageInfo }: { pageInfo: PageInfo }) => {
return (
<div className="flex items-baseline gap-2 flex-1 min-w-0">
<h1 className="text-base font-semibold text-foreground truncate">{pageInfo.title}</h1>
{pageInfo.subtitle && (
<>
<span className="text-muted-foreground">·</span>
<p className="text-sm text-muted-foreground truncate">{pageInfo.subtitle}</p>
</>
)}
</div>
);
};
// 主组件
export function SiteHeader() {
const {Dashboard}=useDashboard()
return (
<header
className={cn(
'flex h-[--header-height] shrink-0 items-center gap-2 border-b border-border',
'transition-[width,height] ease-linear',
'group-has-data-[collapsible=icon]/sidebar-wrapper:h-[--header-height]',
)}
>
<div className="flex w-full items-center gap-2 px-4 py-2 lg:gap-3 lg:px-6">
{/* 侧边栏触发器 */}
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="h-4" />
{/* 页面标题区域 */}
<PageTitleSection pageInfo={Dashboard.pageInfo} />
{/* 右侧内容区域 */}
<div className="flex items-center gap-3 ml-auto">{Dashboard.pageInfo?.rightContent || <DefaultTimeDisplay />}</div>
</div>
</header>
);
}