149 lines
3.8 KiB
TypeScript
149 lines
3.8 KiB
TypeScript
import type { ProFormColumnsType } from "@ant-design/pro-components";
|
|
import { BetaSchemaForm } from "@ant-design/pro-components";
|
|
import { Button, type ColProps, Drawer, Space } from "antd";
|
|
import type { FormInstance } from "antd/lib";
|
|
import React, {
|
|
Children,
|
|
cloneElement,
|
|
forwardRef,
|
|
useImperativeHandle,
|
|
} from "react";
|
|
|
|
interface ConfigurableDrawerFormProps {
|
|
title?: string;
|
|
columns?: ProFormColumnsType[];
|
|
onSubmit?: (values: any) => Promise<boolean>;
|
|
initialValues?: Record<string, any>;
|
|
width?: number | string;
|
|
labelCol?: ColProps;
|
|
wrapperCol?: ColProps;
|
|
footer?: React.ReactNode;
|
|
children?: React.ReactNode;
|
|
bodyStyle?: React.CSSProperties;
|
|
}
|
|
|
|
export interface ConfigurableDrawerFormRef {
|
|
open: (data?: Record<string, any>) => void;
|
|
close: () => void;
|
|
}
|
|
|
|
const ConfigurableDrawerForm = forwardRef<
|
|
ConfigurableDrawerFormRef,
|
|
ConfigurableDrawerFormProps
|
|
>(
|
|
(
|
|
{
|
|
title = "表单",
|
|
labelCol = { span: 4 },
|
|
wrapperCol = { span: 20 },
|
|
columns,
|
|
onSubmit,
|
|
initialValues,
|
|
width = 600,
|
|
footer,
|
|
children,
|
|
bodyStyle = {},
|
|
},
|
|
ref
|
|
) => {
|
|
const [open, setOpen] = React.useState(false);
|
|
const [formData, setFormData] = React.useState(initialValues || {});
|
|
const [loading, setLoading] = React.useState<boolean>(false);
|
|
// 添加表单实例引用
|
|
const formRef = React.useRef<FormInstance>(null);
|
|
useImperativeHandle(ref, () => ({
|
|
open: (data) => {
|
|
if (data) {
|
|
setFormData(data);
|
|
}
|
|
console.log("open");
|
|
setOpen(true);
|
|
},
|
|
close: () => setOpen(false),
|
|
}));
|
|
const renderChildren = () => {
|
|
return Children.map(children, (child) => {
|
|
if (React.isValidElement(child)) {
|
|
// 使用更安全的方式传递属性,避免 TypeScript 错误
|
|
return cloneElement(child, {
|
|
...formData,
|
|
} as any);
|
|
}
|
|
return child;
|
|
});
|
|
};
|
|
const handleSubmit = async () => {
|
|
try {
|
|
if (onSubmit) {
|
|
await formRef.current?.validateFields();
|
|
setLoading(true);
|
|
const values = formRef.current?.getFieldsValue();
|
|
const success = await onSubmit(values);
|
|
if (success) {
|
|
setOpen(false);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Drawer
|
|
title={title}
|
|
styles={{
|
|
header: {
|
|
textAlign: "left",
|
|
position: "relative",
|
|
},
|
|
body: {
|
|
background: "var(--ant-background-color)",
|
|
padding: "var(--ant-padding-lg)",
|
|
...bodyStyle,
|
|
},
|
|
}}
|
|
destroyOnHidden
|
|
closable={true} // 隐藏默认关闭按钮
|
|
open={open}
|
|
onClose={() => setOpen(false)}
|
|
width={width}
|
|
footer={
|
|
<Space style={{ width: "100%", justifyContent: "end" }}>
|
|
{footer ? (
|
|
footer
|
|
) : (
|
|
<>
|
|
<Button onClick={() => setOpen(false)}>取消</Button>
|
|
<Button loading={loading} type="primary" onClick={handleSubmit}>
|
|
保存
|
|
</Button>
|
|
</>
|
|
)}
|
|
</Space>
|
|
}
|
|
>
|
|
{columns ? (
|
|
<BetaSchemaForm
|
|
initialValues={formData}
|
|
layoutType="Form"
|
|
formRef={formRef}
|
|
columns={columns}
|
|
layout="horizontal"
|
|
labelCol={labelCol}
|
|
wrapperCol={wrapperCol}
|
|
submitter={false}
|
|
/>
|
|
) : (
|
|
renderChildren()
|
|
// children
|
|
)}
|
|
</Drawer>
|
|
);
|
|
}
|
|
);
|
|
|
|
export default ConfigurableDrawerForm;
|