From 04bec3aa841e7667bb6028a5fb2d611855be7e1a Mon Sep 17 00:00:00 2001 From: Rogee Date: Thu, 24 Sep 2026 17:10:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E9=A1=B5=E5=A4=B4=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=8C=89=E9=92=AE=E7=8B=AC=E7=AB=8B=E6=88=90=E8=A1=8C?= =?UTF-8?q?=E2=80=94=E2=80=94=E6=A0=87=E9=A2=98=E4=B8=8B=20content=20?= =?UTF-8?q?=E6=A7=BD=E5=8F=B3=E4=BE=A7=E5=AF=B9=E9=BD=90=EF=BC=8C=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E9=9D=A2=E5=8C=85=E5=B1=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 2 +- web/src/components/PageActions.tsx | 2 +- web/src/layouts/index.tsx | 22 ++++++++++------------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6a98462..1ca699f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -61,7 +61,7 @@ ## UI 规范(antd/pro) -- 页面标题右侧的操作按钮与标题底部对齐(Layout 页头槽内联样式控制,勿在其他位置另造对齐方式)。 +- 页面标题与操作按钮各占一行:标题用 PageContainer 自带 `title`/`subTitle`,按钮经 `usePageActions` 注册到 Layout 页头 content 槽(`Flex justify="flex-end"`),不写自定义对齐样式,勿在其他位置另造对齐方式。 - 页面级操作按钮通过 `usePageActions` 注册到页头槽,不得在卡片内重复渲染。 - 弃用 API 禁止回潮:`Alert` 用 `title`/`description`(非 `message`)、纵向堆叠用 `Flex vertical`(非 `Space direction`)、静态 `message.xxx` 改 `App.useApp()`。以 `antd lint` 结果为准。 diff --git a/web/src/components/PageActions.tsx b/web/src/components/PageActions.tsx index c7a6629..a750d54 100644 --- a/web/src/components/PageActions.tsx +++ b/web/src/components/PageActions.tsx @@ -1,7 +1,7 @@ import { createContext, useContext, useEffect } from 'react'; import type { ReactNode } from 'react'; -// 页头动作槽:页面挂载时把自己的操作按钮注册到布局 PageContainer 的 extra(与标题同一行), +// 页头动作槽:页面挂载时把自己的操作按钮注册到布局 PageContainer 的 content(标题下方独立操作行,右侧对齐), // 卸载时自动清除。Layout 提供 Provider,页面只消费 usePageActions。 const PageActionsContext = createContext<(node: ReactNode) => void>(() => {}); diff --git a/web/src/layouts/index.tsx b/web/src/layouts/index.tsx index a53faee..ec21af3 100644 --- a/web/src/layouts/index.tsx +++ b/web/src/layouts/index.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import type { ReactNode } from 'react'; import { history, Outlet, useLocation } from '@umijs/max'; import { PageContainer, ProLayout } from '@ant-design/pro-components'; -import { App, Dropdown, Typography } from 'antd'; +import { App, Dropdown, Flex } from 'antd'; import { LogoutOutlined } from '@ant-design/icons'; import { PageActionsContext } from '@/components/PageActions'; import { menu, menuSelectedKey, pageMetadata } from '@/utils/metadata'; @@ -12,7 +12,7 @@ import { menu, menuSelectedKey, pageMetadata } from '@/utils/metadata'; // (渲染器不传 children prop,用 children 会导致整页空白且无任何报错)。 export default function Layout() { const location = useLocation(); - // 页头动作槽:列表页在挂载时把自己的添加类按钮注册进来,与标题渲染在同一行。 + // 页头动作槽:列表页在挂载时把自己的添加类按钮注册进来,渲染在标题下方的独立操作行(右侧)。 const [pageActions, setPageActions] = useState(null); if (location.pathname === '/login') return ; @@ -58,20 +58,18 @@ export default function Layout() { ), }} > - {/* 页面标题在卡片外(内容区左上角),动作按钮与标题同一行(右侧);卡片内不再重复渲染标题。 */} + {/* 页面标题在卡片外(内容区左上角),动作按钮单独一行渲染在标题下方(content 槽,右侧对齐);卡片内不再重复渲染标题。 */} {/* App 包裹:App.useApp() 的 message 等实例需要此上下文(component=false 不增加 DOM,避免破坏 ProLayout 布局)。 */} - {meta.title} - {meta.subtitle} - - } - subTitle={false} - // 官方 skill 规范:标题右侧操作按钮底部对齐(PageContainer 的 -row 未设 align-items,默认居中)。 - extra={
{pageActions}
} + title={meta.title} + subTitle={meta.subtitle} + // 全站不展示面包屑导航(官方关闭方式:breadcrumbRender={false})。 + breadcrumbRender={false} + // 标题与操作按钮各占一行:标题走 PageContainer 自带 title/subTitle,按钮走 content 槽, + // 右对齐用 Flex 组件 API,不写自定义对齐样式。 + content={pageActions ? {pageActions} : undefined} >