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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
/**
|
||
* 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"
|