统一编辑模板并移除首批台账工具(05-31-business-edit-template-remove-ledger-tools-wave1)
这个提交包含在:
@@ -0,0 +1,162 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { Button } from "../ui/button";
|
||||
import { WorkspaceHeader } from "./ListWorkspace";
|
||||
import { SectionPanel } from "./SectionPanel";
|
||||
|
||||
export function BusinessEditTemplate({
|
||||
eyebrow,
|
||||
title,
|
||||
backTo,
|
||||
backLabel = "返回",
|
||||
status,
|
||||
actions,
|
||||
meta,
|
||||
validation,
|
||||
bottomActions,
|
||||
children,
|
||||
className,
|
||||
testId,
|
||||
}: {
|
||||
eyebrow?: string;
|
||||
title: string;
|
||||
backTo?: string;
|
||||
backLabel?: string;
|
||||
status?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
meta?: ReactNode;
|
||||
validation?: ReactNode;
|
||||
bottomActions?: ReactNode;
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
testId?: string;
|
||||
}) {
|
||||
const headerActions = actions || status || backTo ? (
|
||||
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||
{status ? <div className="shrink-0">{status}</div> : null}
|
||||
{actions}
|
||||
{backTo ? (
|
||||
<Button asChild type="button" variant="secondary">
|
||||
<Link to={backTo}>{backLabel}</Link>
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={cn("page-scaffold", bottomActions && "pb-24 md:pb-0", className)} data-testid={testId}>
|
||||
<WorkspaceHeader eyebrow={eyebrow} title={title} meta={meta} actions={headerActions} />
|
||||
{validation ? <BusinessEditValidationSummary>{validation}</BusinessEditValidationSummary> : null}
|
||||
{children}
|
||||
{bottomActions ? <BusinessEditActionBar>{bottomActions}</BusinessEditActionBar> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function BusinessEditWorkspace({
|
||||
children,
|
||||
className,
|
||||
testId,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
testId?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className={cn("detail-workspace-grid", className)} data-testid={testId}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function BusinessEditMain({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return <div className={cn("space-y-5", className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export function BusinessEditAside({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return <div className={cn("space-y-5", className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export function BusinessEditSection({
|
||||
title,
|
||||
description,
|
||||
actions,
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
title: string;
|
||||
description?: string;
|
||||
actions?: ReactNode;
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<SectionPanel title={title} description={description} actions={actions} className={className}>
|
||||
{children}
|
||||
</SectionPanel>
|
||||
);
|
||||
}
|
||||
|
||||
export function BusinessEditFormGrid({
|
||||
children,
|
||||
className,
|
||||
columns = 2,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
columns?: 1 | 2 | 3;
|
||||
}) {
|
||||
const columnClass = {
|
||||
1: "grid-cols-1",
|
||||
2: "md:grid-cols-2",
|
||||
3: "md:grid-cols-2 xl:grid-cols-3",
|
||||
}[columns];
|
||||
|
||||
return <div className={cn("grid gap-4", columnClass, className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export function BusinessEditValidationSummary({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className={cn("rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700", className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function BusinessEditActionBar({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"mobile-sticky-action-surface fixed inset-x-0 bottom-0 z-50 border-t border-zinc-200 bg-white/95 shadow-[0_-10px_24px_rgba(15,23,42,0.10)] backdrop-blur md:static md:inset-auto md:mt-5 md:rounded-lg md:border md:bg-white md:p-3 md:shadow-none",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="mobile-sticky-action-grid md:flex md:justify-end md:gap-2">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户