fix(pc-detail-responsive-approval-polish): 协调详情断点并收敛审批展示
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-08-03 21:31:44 +08:00
父节点 a5b7e18507
当前提交 c018ea4eb8
共修改 14 个文件,包含 642 行新增和 71 行删除
+1 -1
查看文件
@@ -3,7 +3,7 @@ import { NavLinks } from "./NavLinks";
export function Sidebar() {
return (
<aside className="app-shell-sidebar fixed inset-y-0 z-20 hidden w-72 overflow-hidden border-r border-slate-200 lg:flex lg:flex-col">
<aside className="app-shell-sidebar fixed inset-y-0 z-20 hidden w-72 overflow-hidden border-r border-slate-200 xl:flex xl:flex-col">
<div className="border-b border-slate-200 px-6 py-5">
<AppBrand />
</div>
+1 -1
查看文件
@@ -143,7 +143,7 @@ export function Topbar() {
<div className="flex min-w-0 items-center gap-3">
<Dialog open={mobileNavOpen} onOpenChange={setMobileNavOpen}>
<DialogTrigger asChild>
<Button className="lg:hidden" size="icon" variant="secondary" aria-label="打开菜单" type="button">
<Button className="xl:hidden" size="icon" variant="secondary" aria-label="打开菜单" type="button">
<MenuIcon />
</Button>
</DialogTrigger>
@@ -1,4 +1,4 @@
import { Children, type ReactNode } from "react";
import { Children, Fragment, isValidElement, type ReactNode } from "react";
import { cn } from "../../lib/utils";
import { SectionPanel } from "./SectionPanel";
@@ -71,6 +71,15 @@ export function BusinessDetailFact({
);
}
function hasVisibleNode(node: ReactNode): boolean {
return Children.toArray(node).some((child) => {
if (isValidElement(child) && child.type === Fragment) {
return hasVisibleNode(child.props.children);
}
return true;
});
}
export function BusinessDetailActionPanel({
title = "操作",
status,
@@ -92,21 +101,29 @@ export function BusinessDetailActionPanel({
className?: string;
testId?: string;
}) {
const visibleChildren = Children.toArray(children);
const hasActionContent = Boolean(primaryAction || secondaryActions || moreActions);
const hasChildren = visibleChildren.length > 0;
const hasContentBeforeSummary = Boolean(primaryAction || secondaryActions || moreActions || hasChildren);
const hasStatus = hasVisibleNode(status);
const hasPrimaryAction = hasVisibleNode(primaryAction);
const hasSecondaryActions = hasVisibleNode(secondaryActions);
const hasMoreActions = hasVisibleNode(moreActions);
const hasSummary = hasVisibleNode(summary);
const hasChildren = hasVisibleNode(children);
const hasActionContent = hasPrimaryAction || hasSecondaryActions || hasMoreActions;
const hasContentBeforeSummary = hasActionContent || hasChildren;
if (!hasStatus && !hasActionContent && !hasSummary && !hasChildren) {
return null;
}
return (
<SectionPanel title={title} actions={status} className={cn("detail-action-panel lg:sticky lg:top-24", className)}>
<div className="detail-action-stack" data-testid={testId}>
{primaryAction ? <div className="grid gap-2">{primaryAction}</div> : null}
{secondaryActions ? <div className="workflow-action-bar">{secondaryActions}</div> : null}
{moreActions ? <div className="border-t border-zinc-200 pt-3">{moreActions}</div> : null}
{hasPrimaryAction ? <div className="grid gap-2">{primaryAction}</div> : null}
{hasSecondaryActions ? <div className="workflow-action-bar">{secondaryActions}</div> : null}
{hasMoreActions ? <div className="border-t border-zinc-200 pt-3">{moreActions}</div> : null}
{hasChildren ? (
<div className={cn(hasActionContent && "border-t border-zinc-200 pt-3")}>{children}</div>
) : null}
{summary ? (
{hasSummary ? (
<div className={cn(hasContentBeforeSummary && "border-t border-zinc-200 pt-3")}>
<div className="space-y-2 text-sm text-zinc-600">{summary}</div>
</div>