"use client" import type { ReactNode } from "react" import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" export interface FormSection { title?: string description?: string children: ReactNode } export interface FormLayoutProps { /** 表单标题 */ title?: string /** 表单描述 */ description?: string /** 表单部分 */ sections?: FormSection[] /** 表单内容 */ children?: ReactNode /** 提交按钮文本 */ submitText?: string /** 取消按钮文本 */ cancelText?: string /** 是否显示取消按钮 */ showCancel?: boolean /** 是否显示重置按钮 */ showReset?: boolean /** 重置按钮文本 */ resetText?: string /** 提交处理函数 */ onSubmit?: () => void /** 取消处理函数 */ onCancel?: () => void /** 重置处理函数 */ onReset?: () => void /** 是否禁用提交按钮 */ submitDisabled?: boolean /** 是否显示加载状态 */ loading?: boolean /** 自定义底部内容 */ footer?: ReactNode /** 自定义类名 */ className?: string /** 是否使用卡片包装 */ withCard?: boolean /** 表单布局方向 */ direction?: "vertical" | "horizontal" /** 表单标签宽度 (仅在水平布局时有效) */ labelWidth?: string } /** * 统一的表单布局组件 */ export function FormLayout({ title, description, sections = [], children, submitText = "提交", cancelText = "取消", showCancel = true, showReset = false, resetText = "重置", onSubmit, onCancel, onReset, submitDisabled = false, loading = false, footer, className, withCard = true, direction = "vertical", labelWidth = "120px", }: FormLayoutProps) { const FormContent = () => ( <> {/* 表单内容 */}
{/* 如果有sections,渲染sections */} {sections.length > 0 ? sections.map((section, index) => (
{(section.title || section.description) && (
{section.title &&

{section.title}

} {section.description &&

{section.description}

}
)}
{section.children}
)) : // 否则直接渲染children children}
{/* 表单底部 */} {(onSubmit || onCancel || onReset || footer) && (
{footer || ( <> {showReset && onReset && ( )} {showCancel && onCancel && ( )} {onSubmit && ( )} )}
)} ) // 添加水平布局的样式 if (direction === "horizontal") { const style = document.createElement("style") style.textContent = ` .form-horizontal .form-item { display: flex; align-items: flex-start; margin-bottom: 1rem; } .form-horizontal .form-label { width: ${labelWidth}; flex-shrink: 0; padding-top: 0.5rem; } .form-horizontal .form-field { flex: 1; } @media (max-width: 640px) { .form-horizontal .form-item { flex-direction: column; align-items: stretch; } .form-horizontal .form-label { width: 100%; margin-bottom: 0.5rem; padding-top: 0; } } ` document.head.appendChild(style) } // 根据是否需要卡片包装返回不同的渲染结果 if (withCard) { return ( {(title || description) && ( {title && {title}} {description && {description}} )} ) } return (
{(title || description) && (
{title &&

{title}

} {description &&

{description}

}
)}
) } /** * 表单项组件 - 用于水平布局 */ export function FormItem({ label, required, children }: { label: string; required?: boolean; children: ReactNode }) { return (
{required && *} {label}:
{children}
) }