Files
xiaoxia-saas/apps/web/src/components/layout/PageHead/index.tsx
T
xiaoxia 18f534bbd6
CI/CD Pipeline / Canary Release to Production (push) Failing after 1158h6m59s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1158h30m59s
CI/CD Pipeline / Deploy Production (push) Failing after 1158h31m6s
CI/CD Pipeline / CI Gate (push) Failing after 1158h32m0s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 1158h32m2s
CI/CD Pipeline / Build Production Web Image (push) Failing after 1158h32m4s
CI/CD Pipeline / Build Production API Image (push) Failing after 1158h32m6s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 1158h43m16s
CI/CD Pipeline / PR Build Web Image (push) Failing after 1158h43m16s
CI/CD Pipeline / PR Build API Image (push) Failing after 1158h43m17s
CI/CD Pipeline / Frontend Lint (push) Failing after 1158h43m17s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 1158h43m18s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m1s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 6m1s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 2m27s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m19s
CI/CD Pipeline / Unit Tests (push) Successful in 10m15s
CI/CD Pipeline / Integration Tests (push) Successful in 3m8s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m24s
CI/CD Pipeline / Build Staging API Image (push) Successful in 16m22s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m38s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 5m33s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m19s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 52s
refactor(PageHead): 页面头部组件目录化拆分(182→97行, -47%) (#1177)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-07-30 08:40:05 +08:00

92 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* PageHead - 页面头部组件(Task 1.4)
*
* 功能:
* - 页面标题展示
* - 面包屑导航(自动根据路由生成,也支持手动传入)
* - 右侧操作按钮区(slot,由页面自行填充)
* - 响应式:移动端简化布局(隐藏面包屑,缩小标题)
*
* 复用 global.css 中已有的 .xx-page-head 基础样式,
* 补充面包屑、操作区等扩展样式。
*/
import React from "react"
import { useLocation, useNavigate, Link } from "react-router-dom"
import { RightOutlined, HomeOutlined } from "@ant-design/icons"
import type { PageHeadProps } from "./types"
import { generateBreadcrumb } from "./utils"
import "./PageHead.css"
const PageHead: React.FC<PageHeadProps> = ({
title,
description,
breadcrumb,
actions,
hideBreadcrumb = false,
}) => {
const location = useLocation()
const navigate = useNavigate()
// 使用传入的面包屑或自动生成
const breadcrumbItems = breadcrumb ?? generateBreadcrumb(location.pathname)
// 首页不显示面包屑
const showBreadcrumb =
!hideBreadcrumb &&
breadcrumbItems.length > 1 &&
location.pathname !== "/app" &&
location.pathname !== "/app/dashboard"
return (
<header className="xx-page-head">
<div className="xx-page-head-left">
{/* 面包屑导航 */}
{showBreadcrumb && (
<nav className="xx-page-breadcrumb" aria-label="面包屑导航">
<ol>
{breadcrumbItems.map((item, index) => {
const isLast = index === breadcrumbItems.length - 1
return (
<li key={`${item.label}-${index}`} className="xx-page-breadcrumb-item">
{index > 0 && <RightOutlined className="xx-page-breadcrumb-separator" />}
{item.path && !isLast ? (
<Link
to={item.path}
className="xx-page-breadcrumb-link"
onClick={(e) => {
e.preventDefault()
navigate(item.path!)
}}
>
{index === 0 ? <HomeOutlined className="xx-page-breadcrumb-home" /> : null}
<span>{item.label}</span>
</Link>
) : (
<span className="xx-page-breadcrumb-current" aria-current="page">
{index === 0 ? <HomeOutlined className="xx-page-breadcrumb-home" /> : null}
<span>{item.label}</span>
</span>
)}
</li>
)
})}
</ol>
</nav>
)}
{/* 标题 + 描述 */}
<div className="xx-page-head-title">
<h2>{title}</h2>
{description && <p>{description}</p>}
</div>
</div>
{/* 右侧操作区 */}
{actions && <div className="xx-page-head-actions">{actions}</div>}
</header>
)
}
export default PageHead
export type { BreadcrumbItem, PageHeadProps } from "./types"