8.5 KiB
8.5 KiB
FormPreview 使用指南
📖 概述
FormPreview 是一个独立的表单预览组件,从 FormDesigner 中提取出来,可在任何地方使用。它支持完整的表单交互、验证和联动规则。
✨ 特点
- ✅ 完全独立:可在任何页面使用,不依赖 FormDesigner
- ✅ 支持所有字段类型:input, select, textarea, date, grid, cascader 等
- ✅ 支持验证规则:required, pattern, min/max, email, phone 等
- ✅ 支持联动规则:显示/隐藏、禁用/启用、必填控制、值联动
- ✅ 支持动态数据源:API 数据源、预定义数据源
- ✅ 非受控组件:内部管理状态,无冲突
- ✅ 简单易用:只需传入
fields和formConfig
📦 导入
import { FormPreview, FormPreviewRef } from '@/components/FormDesigner';
import type { FieldConfig, FormConfig } from '@/components/FormDesigner';
🚀 基础用法
1. 最简单的使用
import React, { useRef } from 'react';
import { FormPreview, FormPreviewRef } from '@/components/FormDesigner';
const MyComponent = () => {
const previewRef = useRef<FormPreviewRef>(null);
// 从后端获取表单定义
const formSchema = await getFormDefinitionById(id);
return (
<FormPreview
ref={previewRef}
fields={formSchema.fields}
formConfig={formSchema.formConfig}
/>
);
};
2. 在 Modal 中使用
import React from 'react';
import { Modal } from 'antd';
import { FormPreview } from '@/components/FormDesigner';
const FormPreviewModal = ({ open, onClose, formDefinition }) => {
if (!formDefinition) return null;
const { schema } = formDefinition;
return (
<Modal
title={`预览表单:${formDefinition.name}`}
open={open}
onCancel={onClose}
footer={null}
width={schema.formConfig.formWidth || 600}
styles={{
body: {
maxHeight: '70vh',
overflowY: 'auto',
padding: 0,
}
}}
>
<FormPreview
fields={schema.fields}
formConfig={schema.formConfig}
/>
</Modal>
);
};
3. 使用 Ref 方法
import React, { useRef } from 'react';
import { Button } from 'antd';
import { FormPreview, FormPreviewRef } from '@/components/FormDesigner';
const MyComponent = () => {
const previewRef = useRef<FormPreviewRef>(null);
const handleSubmit = async () => {
// 触发表单验证和提交
await previewRef.current?.submit();
};
const handleReset = () => {
// 重置表单
previewRef.current?.reset();
};
return (
<div>
<FormPreview
ref={previewRef}
fields={fields}
formConfig={formConfig}
/>
<div style={{ marginTop: 16 }}>
<Button type="primary" onClick={handleSubmit}>提交</Button>
<Button onClick={handleReset} style={{ marginLeft: 8 }}>重置</Button>
</div>
</div>
);
};
📝 Props 说明
FormPreviewProps
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
fields |
FieldConfig[] |
✅ | 字段列表 |
formConfig |
FormConfig |
✅ | 表单配置 |
FormPreviewRef 方法
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
submit() |
无 | Promise<void> |
提交表单(触发验证) |
reset() |
无 | void |
重置表单 |
🔧 数据格式
FormConfig 示例
const formConfig: FormConfig = {
title: "部署申请表单", // 表单标题(可选)
formWidth: 600, // 表单弹窗宽度,单位px
labelAlign: "right", // 标签对齐:left | right | top
size: "middle" // 表单尺寸:small | middle | large
};
Fields 示例
const fields: FieldConfig[] = [
// 基础输入框
{
id: "field_1",
type: "input",
label: "应用名称",
name: "appName",
placeholder: "请输入应用名称",
required: true,
validationRules: [
{ type: "required", message: "应用名称不能为空" },
{ type: "maxLength", value: 50, message: "不能超过50个字符" }
]
},
// 下拉选择(静态选项)
{
id: "field_2",
type: "select",
label: "环境选择",
name: "environment",
required: true,
dataSourceType: "static",
options: [
{ label: "开发环境", value: "dev" },
{ label: "测试环境", value: "test" },
{ label: "生产环境", value: "prod" }
]
},
// 下拉选择(API 数据源)
{
id: "field_3",
type: "select",
label: "Jenkins服务器",
name: "jenkinsServer",
required: true,
dataSourceType: "api",
apiDataSource: {
url: "/api/v1/jenkins-servers/list",
method: "GET",
params: { enabled: true },
labelField: "name",
valueField: "id"
}
},
// 下拉选择(预定义数据源)
{
id: "field_4",
type: "select",
label: "项目组",
name: "projectGroup",
required: true,
dataSourceType: "predefined",
predefinedDataSource: {
sourceType: "PROJECT_GROUPS"
}
},
// 栅格布局
{
id: "field_5",
type: "grid",
label: "基础信息",
name: "grid_basic",
columns: 2,
columnSpans: [12, 12],
gutter: 16,
children: [
// 第一列
[
{
id: "field_6",
type: "input",
label: "创建人",
name: "creator",
required: true
}
],
// 第二列
[
{
id: "field_7",
type: "date",
label: "创建日期",
name: "createDate",
required: true
}
]
]
}
];
🌟 实际应用场景
场景1:工作流设计页面预览启动表单
// src/pages/Workflow/Design/components/FormPreviewModal.tsx
import { FormPreview } from '@/components/FormDesigner';
const FormPreviewModal = ({ formDefinition, open, onClose }) => {
const { schema } = formDefinition;
return (
<Modal open={open} onCancel={onClose} width={schema.formConfig.formWidth}>
<FormPreview
fields={schema.fields}
formConfig={schema.formConfig}
/>
</Modal>
);
};
场景2:表单设计器内部预览
// src/components/FormDesigner/Designer.tsx
const FormDesigner = () => {
const [previewVisible, setPreviewVisible] = useState(false);
const [fields, setFields] = useState<FieldConfig[]>([]);
const [formConfig, setFormConfig] = useState<FormConfig>({});
return (
<>
<Button onClick={() => setPreviewVisible(true)}>预览</Button>
<Modal open={previewVisible} onCancel={() => setPreviewVisible(false)}>
<FormPreview fields={fields} formConfig={formConfig} />
</Modal>
</>
);
};
场景3:独立的表单预览页面
// src/pages/Form/Preview/index.tsx
import { useParams } from 'react-router-dom';
import { FormPreview } from '@/components/FormDesigner';
const FormPreviewPage = () => {
const { id } = useParams();
const [formSchema, setFormSchema] = useState(null);
useEffect(() => {
const loadForm = async () => {
const data = await getFormDefinitionById(id);
setFormSchema(data.schema);
};
loadForm();
}, [id]);
if (!formSchema) return <div>加载中...</div>;
return (
<div className="container">
<h1>表单预览</h1>
<FormPreview
fields={formSchema.fields}
formConfig={formSchema.formConfig}
/>
</div>
);
};
⚠️ 重要说明
1. 非受控组件
FormPreview 是非受控组件,内部通过 Ant Design Form 管理状态:
- ✅ 不要传递
value和onChange(会导致冲突) - ✅ 不要尝试从外部控制字段值
- ✅ 使用
ref方法获取表单值或提交表单
2. 数据格式统一
无论在哪里使用,数据格式都是一致的:
<FormPreview
fields={formSchema.fields} // FieldConfig[]
formConfig={formSchema.formConfig} // FormConfig
/>
3. 与 FormRenderer 的区别
| 特性 | FormPreview | FormRenderer |
|---|---|---|
| 推荐使用 | ✅ 是 | ❌ 已废弃 |
| 受控模式 | ❌ 非受控 | ⚠️ 部分受控(有问题) |
| 下拉框可选中 | ✅ 正常 | ❌ 有bug |
| 使用场景 | 预览、交互 | 已废弃 |
建议:所有新代码都使用 FormPreview,不要再使用 FormRenderer。