技术介绍

该代码实现了一个高度可配置的表单模态框组件FormModal,基于React和Ant Design构建。核心功能包括动态表单渲染、多列布局支持、多种输入类型适配(文本、日期、下拉选择等),以及与父组件的交互控制。

标题与布局设计

标题通过title属性动态传入,支持自定义。布局设计特点:

  • 支持单列或多列布局(通过columns参数控制)
  • 使用Ant Design的RowCol组件实现响应式网格
  • 可通过gutter参数调整列间距
  • 表单布局模式(formLayout)支持水平或垂直排列

动态表单渲染

  • 通过fields数组配置表单字段
  • 支持多种字段类型:文本输入、数字输入、文本域、日期选择器和下拉选择框
  • 每个字段可单独配置验证规则、提示信息和禁用状态

类型处理优化

  • 使用switch-case结构处理不同输入类型
  • 为每种输入类型提取公共属性(commonProps
  • 支持直接传入自定义组件(通过component属性)

状态管理

  • 使用Ant Design Form的useForm hook管理表单状态
  • 通过initialValues实现数据回填
  • 弹窗关闭时自动重置表单

以下是代码 

import React, { useEffect } from 'react';
import { Modal, Form, Input, Row, Col, DatePicker, Select } from 'antd';

const FormModal = ({
    visible,
    onCancel,
    onOk,
    title,
    initialValues = null,
    fields,
    columns = 2,
    gutter = 16,
    formLayout = 'vertical',
    okText = "确定",
    cancelText = "取消"
}) => {
    const [form] = Form.useForm();
    // 当initialValues变化时,重置表单
    React.useEffect(() => {
        if (visible) {
            form.setFieldsValue(initialValues || {});
        }
    }, [visible, initialValues, form]);

    const handleOk = async () => {
        try {
            const values = await form.validateFields();
            onOk(values, initialValues);
        } catch (error) {
            console.error('表单验证失败:', error);
        }
    };

    // 渲染输入组件
    const renderInputComponent = (field) => {
        const commonProps = {
            placeholder: `请输入${field.label}`,
            disabled: field.disabled,
            ...field
        };

        // 根据字段类型渲染不同的输入组件
        switch (field.type) {
            case 'textarea':
                return <Input.TextArea {...commonProps} rows={4} />;
            case 'date':
                return <DatePicker {...commonProps} style={{ width: '100%' }} />;
            case 'select':
                return (
                    <Select {...commonProps} options={field.options}>
                        {field.options?.map(option => (
                            <Select.Option key={option.value} value={option.value}>
                                {option.label}
                            </Select.Option>
                        ))}
                    </Select>
                );
            case 'number':
                return <Input type="number" {...commonProps} />;
            default:
                return <Input {...commonProps} />;
        }
    };

    // 渲染表单字段
    const renderFormFields = () => {
        if (columns === 1) {
            // 单列布局
            return fields.map(field => (
                <Form.Item
                    key={field.name}
                    name={field.name}
                    label={field.label}
                    rules={field.rules}
                    extra={field.extra}
                    tooltip={field.tooltip}
                >
                    {field.component || renderInputComponent(field)}
                </Form.Item>
            ));
        }

        // 多列布局
        const rows = [];
        for (let i = 0; i < fields.length; i += columns) {
            const rowFields = fields.slice(i, i + columns);

            const rowItems = rowFields.map(field => (
                <Col span={24 / columns} key={field.name}>
                    <Form.Item
                        name={field.name}
                        label={field.label}
                        rules={field.rules}
                        extra={field.extra}
                        tooltip={field.tooltip}
                    >
                        {field.component || renderInputComponent(field)}
                    </Form.Item>
                </Col>
            ));

            rows.push(
                <Row gutter={gutter} key={`row-${i}`}>
                    {rowItems}
                </Row>
            );
        }

        return rows;
    };

    return (
        <Modal
            afterClose={() => {
                // 弹窗完全关闭后再次重置表单
                form.resetFields();
            }}
            title={title}
            visible={visible}
            onOk={handleOk}
            onCancel={() => {
                form.resetFields();
                onCancel();
            }}
            okText={okText}
            cancelText={cancelText}
            destroyOnClose
            width={800} // 增加宽度以适应更多字段
        >
            <Form
                form={form}
                layout={formLayout}
                initialValues={initialValues || {}}
            >
                {renderFormFields()}
            </Form>
        </Modal>
    );
};

export default FormModal;
  <FormModal
               title={'编辑'}
                visible={modifyOrderModal}
                onOk={modifyOrderModalOk}
                onCancel={modifyOrderModalCancel}
                fields={modifyOrderFields}
                initialValues={selectedRowOrder}
            >
            </FormModal>
const modifyOrderFields = [
        {
            name: 'orderNo',
            label: '工单名称',
            rules: [{ required: true, message: '请输入工单名称' }]
        },
        {
            name: 'orderNo',
            label: '标准工时',
            rules: [{ required: true, message: '请输入标准工时' }],
            type: 'number'
        },
        {
            name: 'orderCount',
            label: '工单数',
            rules: [{ required: true, message: '请输入工单数' }],
            type: 'number'

        },
    ]

扩展性有待提高

更多推荐