antd4 from拆分

期望一个新增页面,由多个表单构成,按钮提交统一校验

思路 需要把各个form实例保存下来,按钮提交时统一触发校验

父组件

<div className={styles.container}>
                <Form.Provider
                    onFormFinish={name => {
                        if (name === 'form1') {
                            // Do something...
                        }
                    }}
                >
                    <BaseInfoForm {...baseInfoProps}></BaseInfoForm>
                    <ProductInfo currentModel={currentModel} />
                    <AccessoriesInfo currentModel={currentModel} />
                    <OtherForm {...otherInfoProps}></OtherForm>
                </Form.Provider>
                <div className={styles.opsButtons}>
                    <Button
                        onClick={() => {
                            dispatch({
                                type: `${currentModel}/overrideStateProps`,
                                payload: {
                                    shouldRouterChange: false,
                                },
                            });
                            history.goBack();
                        }}
                    >
                        取消
                    </Button>
                    <Button type="primary" loading={loadState} onClick={() => handleSave(true)} htmlType="submit">
                        保存
                    </Button>
                </div>

子组件

import React, { useEffect, useRef } from 'react';
import { Input, Select, Form, Card, Col, Row, Radio } from 'antd';
import ContractBatchNumSelect from '@/components/ContractBatchNumSelect';
import NotSuitableForReturnAndExchange from '@/services/NotSuitableForReturnAndExchange';
import WorkOrdersClientSelect from './components/WorkOrdersClientSelect';
import styles from './index.less';

// 输入框最大字符数
export const INPUT_LENGTH_LIMIT = 50;
// 文本框最大字符数
export const TEXT_AREA_LENGTH_LIMIT = 500;
const whethertoshipStatusList = NotSuitableForReturnAndExchange.whethertoshipStatus();
const numberReg = /^[A-Za-z0-9]+$/;
const Option = Select.Option;
const FormItem = Form.Item;
const FormItemLayout = {
    labelCol: { span: 4 },
    wrapperCol: { span: 20 },
};
const commonInputConfig = {
    maxLength: INPUT_LENGTH_LIMIT,
};
export default ({ currentModel, baseInfo, dispatch }) => {
    const [form] = Form.useForm();
    const { getFieldValue, setFieldsValue } = form;
    const formRef = useRef(null);
    useEffect(() => {
        formRef.current = form;
    }, [form]);
    useEffect(() => {
        dispatch({
            type: `${currentModel}/overrideStateProps`,
            payload: {
                baseForm: formRef,
            },
        });
    }, [dispatch, formRef, currentModel]);
    const handelChangeContractModel = choose => {
        if (choose) {
            const values = {
                client_id: choose.client_id,
                deliverdeliveryClientName: choose.delivery_client_name,
                delivery_client_id: choose.delivery_client_id,
                batch_contract_id: choose.id,
                contract_id: choose.admin_contract_id,
            };
            setFieldsValue({
                ...values,
            });
            dispatch({
                type: `${currentModel}/updateStateProps`,
                payload: {
                    name: 'baseInfo',
                    value: { ...values },
                },
            });
        }
    };
    const onValuesChange = (changedValues, allValues) => {
        const { dates, product_type, ...others } = allValues;
        const params = {
            ...others,
        };
        if (changedValues?.product_type) {
            dispatch({
                type: `${currentModel}/updateStateProps`,
                payload: {
                    name: 'baseInfo',
                    value: { product_id: '', product_type },
                },
            });
            setFieldsValue({
                product_id: '',
                product_type,
            });
        }
        dispatch({
            type: `${currentModel}/updateStateProps`,
            payload: {
                name: 'baseInfo',
                value: { ...params },
            },
        });
        dispatch({
            type: `${currentModel}/overrideStateProps`,
            payload: {
                shouldRouterChange: true,
            },
        });
    };
    return (
        <Form
            name="form2"
            form={form}
            initialValues={{
                client_name: '' || '',
                deliverdeliveryClientName: baseInfo?.deliverdeliveryClientName || '',
            }}
            onValuesChange={onValuesChange}
            {...FormItemLayout}
        >
            <Card title="基本信息" className={styles.card} bordered>
                <Row>
                    <Col span={12}>
                        <FormItem
                            name="client_id"
                            label="客户名称"
                            rules={[{ required: true, message: '请输入选择客户' }]}
                        >
                            {/* <Select
                                            showSearch
                                            allowClear
                                            filterOption={(input, option) => option.props.children.indexOf(input) >= 0}
                                            placeholder="请输入选择客户"
                                            // onChange={e => handelChangeClientsList(e)}
                                        >
                                            {clientsList?.map(ele => {
                                                return (
                                                    <Option key={ele.id} value={ele.id}>
                                                        {ele.name}
                                                    </Option>
                                                );
                                            })}
                                        </Select> */}
                            <WorkOrdersClientSelect placeholder="请输入选择客户" />
                        </FormItem>
                    </Col>
                    <Col span={12}>
                        <FormItem name="title" label="工单标题" rules={[{ required: true, message: '请输入工单标题' }]}>
                            <Input placeholder="请输入工单标题" {...commonInputConfig} />
                        </FormItem>
                    </Col>
                </Row>
                <Row>
                    <Col span={12}>
                        <FormItem
                            name="batch_contract_id"
                            label="合同编号"
                            rules={[{ required: true, message: '请选择合同编号' }]}
                        >
                            <ContractBatchNumSelect
                                onChangeContract={handelChangeContractModel}
                                form={form}
                                clientId={getFieldValue('client_id')}
                                placeholder="请选择合同编号"
                            />
                        </FormItem>
                    </Col>
                    <Col span={12}>
                        <FormItem name="deliverdeliveryClientName" label="发货客户">
                            <Input placeholder="选择合同自动带出" disabled />
                        </FormItem>
                    </Col>
                </Row>
                <Row>
                    <Col span={12}>
                        <FormItem
                            name="delivery_type"
                            label="发货类型"
                            rules={[{ required: true, message: '请选择发货类型' }]}
                        >
                            <Select
                                placeholder="请选择发货类型"
                                showSearch
                                allowClear
                                // disabled={pageType === 'update' && !isCreator && isReviewer}
                            >
                                {whethertoshipStatusList?.map(ele => {
                                    return (
                                        <Option key={ele.key} value={ele.key}>
                                            {ele.name}
                                        </Option>
                                    );
                                })}
                            </Select>
                        </FormItem>
                    </Col>
                    <Col span={12}>
                        <Row>
                            <Col span={12}>
                                <FormItem
                                    name="sendBack"
                                    label="寄回运单号"
                                    labelCol={{
                                        xs: { span: 4 },
                                        sm: { span: 6 },
                                        md: { span: 6 },
                                        lg: { span: 6 },
                                    }}
                                    // wrapperCol={{ span: 20 }}
                                >
                                    <Radio.Group>
                                        <Radio value="back" style={{ whiteSpace: 'nowrap' }}>
                                            同城带回
                                        </Radio>
                                        <Radio value="sendBack" style={{ whiteSpace: 'nowrap' }}>
                                            寄回运单号
                                        </Radio>
                                    </Radio.Group>
                                </FormItem>
                            </Col>
                            <Col span={12}>
                                {baseInfo?.sendBack === 'sendBack' ? (
                                    <FormItem
                                        labelCol={{
                                            xs: { span: 4 },
                                            sm: { span: 6 },
                                            md: { span: 6 },
                                            lg: { span: 6 },
                                        }}
                                        // wrapperCol={{ span: 20 }}
                                        name="send_back_waybill_number"
                                        label="申请编号"
                                        rules={[
                                            {
                                                required: true,
                                                message: '请输入寄回运单号',
                                            },
                                            {
                                                pattern: numberReg,
                                                message: '只能填写字母或数字',
                                            },
                                        ]}
                                    >
                                        <Input placeholder="请输入寄回运单号" />
                                    </FormItem>
                                ) : null}
                            </Col>
                        </Row>
                    </Col>
                </Row>
                <Row>
                    <Col span={12}>
                        <FormItem
                            name="final_client"
                            label="最终客户"
                            rules={[
                                {
                                    required: getFieldValue('client_id') === 175,
                                    message: '请输入最终客户',
                                },
                            ]}
                        >
                            <Input placeholder="请输入最终客户" {...commonInputConfig} />
                        </FormItem>
                    </Col>
                </Row>
            </Card>
        </Form>
    );
};

validateFields 触发表单验证在这里插入图片描述

使用promise.all方法来提交实现:

  var p1 = new Promise((resolve, reject) => {
      console.log(1)
      resolve()
    })
    var p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log(2)
        resolve()
      }, 1000);
    })
    var p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log(3)
        resolve()
      }, 1000);
    })
 
    Promise.all([p1, p2, p3]).then((result) => {
      console.log("执行完毕");
    })

提交校验

    const handleSave = goBack => {
        const baseFormValidateFields = baseForm.current.validateFields();
        const otherFormValidateFields = otherForm.current.validateFields();
        Promise.all([baseFormValidateFields, otherFormValidateFields]).then(result => {
            console.log('执行完毕');
            dispatch({
                type: `${currentModel}/save`,
                payload: {
                    goBack,
                    callback: () => {
                        dispatch({
                            type: 'shipOrderList/getShipOrderList',
                        });
                    },
                },
            });
            dispatch({
                type: `${currentModel}/overrideStateProps`,
                payload: {
                    shouldRouterChange: false,
                },
            });
        });
    };
<think>好的,用户需要寻找与Ant Design相关的设计资源或解决设计问题。首先,我需要回忆Ant Design是什么,它是一个企业级UI设计语言和React组件库,主要用于开发企业级中后台产品。用户可能是在开发过程中遇到了设计上的挑战,或者想要遵循最佳实践来提升项目的质量和一致性。 接下来,用户提到的“设计资源”可能包括组件库、设计规范、模板等,而“设计问题”可能涉及布局、主题定制、可访问性等方面的问题。我需要整理Ant Design的官方资源,比如他们的文档、设计原则、组件库,以及社区提供的额外资源,比如第三方模板或工具。 然后,用户可能遇到的问题可能有几个方面:比如如何定制主题颜色,如何实现响应式布局,如何提升可访问性,或者如何处理复杂表单的交互设计。针对每个问题,需要给出具体的解决方法和示例代码,同时引用Ant Design的官方文档作为参考。 另外,用户提供的参考引用中有提到Chris Richardson关于领域驱动设计和解耦的内容,这可能与Ant Design的模块化设计有关联,可以强调Ant Design如何通过组件化和设计规范来减少代码耦合,提高模块化,但需要确认是否直接相关,避免引入不必要的信息。 最后,生成相关问题需要考虑用户可能的后续疑问,比如如何与后端集成、性能优化、国际化支持等,确保覆盖Ant Design的常见应用场景和挑战。</think>### Ant Design 设计资源与问题解决方案 Ant Design 是面向企业级中后台产品的 UI 设计语言与 React 组件库,提供完整的**设计规范**和**开发工具链**。以下是关键资源和解决方案整理: --- #### 一、核心设计资源 1. **官方设计指南** - **设计原则**:清晰、一致、高效、可控[^1]。 - **色彩体系**:基于 HSB 的 12 级色板,支持动态主题定制(通过 `@ant-design/cssinjs` 实现)。 - **布局系统**:提供栅格系统(Grid)、响应式断点规则(Breakpoints)。 2. **组件库与模板** - **Ant Design Pro**:开箱即用的中后台前端解决方案,集成路由、权限管理等。 - **Figam 资源**:官方提供完整的设计组件库(Sketch/Adobe XD 版本需社区支持)。 3. **开发工具** - **umi**:企业级前端框架,深度集成 Ant Design。 - **dumi**:组件文档生成工具,支持 Markdown 嵌入演示代码。 --- #### 二、常见设计问题与解决方案 1. **主题定制** **问题**:如何快速修改全局品牌色? **方案**:通过 `ConfigProvider` 或 `@ant-design/cssinjs` 动态注入主题变量: ```jsx import { ConfigProvider, Button } from 'antd'; const theme = { token: { colorPrimary: '#1890ff' } }; <ConfigProvider theme={theme}> <Button type="primary">定制按钮</Button> </ConfigProvider> ``` [^1] 2. **复杂表单交互** **问题**:动态增减表单项如何实现? **方案**:使用 `Form.List` 管理动态字段: ```jsx <Form.List name="users"> {(fields, { add, remove }) => ( fields.map(({ key, name }) => ( <Form.Item key={key} name={[name, 'firstName']}> <Input /> </Form.Item> )) )} </Form.List> ``` 3. **可访问性优化** **问题**:如何提升组件对屏幕阅读器的兼容性? **方案**: - 使用 `aria-*` 属性标注组件状态(如 `aria-label` 描述按钮功能)。 - 优先选择支持键盘导航的组件(如 `Menu` 组件默认支持方向键操作)。 --- #### 三、扩展资源推荐 1. **社区生态** - **Ant Design Charts**:数据可视化组件库(折线图、柱状图等)。 - **Pro Components**:高阶组件(如高级表格 `ProTable`)。 2. **最佳实践** - **代码解耦**:避免“大服务”模式(Big Fat Service),通过模块化拆分 UI 逻辑(参考 DDD 设计思想)。 - **性能优化**:使用 `useMemo` 缓存复杂组件渲染结果,减少重复计算。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值