react + Steps 分布表单

634 阅读1分钟

之前涉及到分布表单的需求,当点击Next去下一步的时候将相关表单值存起来,记住第二步的选择状态,当返回第一步时,不改变选择的状态。

StepPage

import { Steps, Breadcrumb, Card, Spin } from 'antd';
import { history } from 'umi';

import { applySubmit } from '@/service/template';

import Step1 from './components/Step1';
import Step2 from './components/Step2';
import Step3 from './components/Step3';
import Step4 from './components/Step4';
import styles from './index.less';

const { Step } = Steps;

const stepsInfo = {
  step1: Step1,
  step2: Step2,
  step3: Step3,
  Step4: Step4,
};

const StepPage = props => {
  const [current, setCurrent] = useState(0);
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState({
    appId: '',
    appName: '',
    templateId: '',
    applyReason: '',
    approvalId: '',
  });

  const changeStep = page => {
    setCurrent(current + page);
  };

  const submit = async props => {
    setLoading(true);
    const res = await applySubmit({
      appId: data.appId,
      templateId: data.templateId,
      ...props,
    });
    setLoading(false);
    if (res && res.success) {
      setData(data => {
        return {
          ...data,
          approvalId: res.approvalId,
        };
      });
    } else {
      return Promise.reject(res);
    }
  };

  const stepText = {
    step1: 'stepText1',
    step2: 'stepText2',
    step3: 'stepText3',
    step4: 'stepText4',
  };

  const stepList = ['selectProgram', 'chooseTemplate', 'sceneDesc', 'finished'];

  const StepComponent = stepsInfo[stepList[current]];

  return (
    <Spin spinning={loading}>
      <div className={styles.indexPage}>
        <div className={styles.headerDesc}>
          <Breadcrumb>
            <Breadcrumb.Item onClick={() => history.replace('/main')}>
              Main
            </Breadcrumb.Item>
            <Breadcrumb.Item onClick={() => history.replace('/main/1')}>
              Main_index
            </Breadcrumb.Item>
          </Breadcrumb>
        </div>
        <div className={styles.header}>Main_index</div>
        <Card bordered={false} className={styles.step}>
          <Steps current={current}>
            {stepList.map(step => (
              <Step key={step} title={stepText[step]} />
            ))}
          </Steps>
        </Card>
        <StepComponent
          step={stepList[current]}
          data={data}
          setData={setData}
          next={(changeCount = 1) => changeStep(changeCount)}
          back={(changeCount = -1) => changeStep(changeCount)}
          submit={submit}
        />
      </div>
    </Spin>
  );
};

export default StepPage;

less

.indexPage {
  width: 100%;
  height: 100%;
  padding: 20px 20px 0;
  .header {
    color: rgba(0, 0, 0, 0.85);
    font-size: 24px;
  }
  .headerDesc {
    color: rgba(4, 15, 36, 0.45);
  }
  .step {
    margin-top: 20px;
    padding: 11px;
    background: @white;
    border-radius: 4px;
    box-shadow: @box-shadow-base;
  }
}

Step1

import { Form, Input, Button, Card, Space } from 'antd';
import { history } from 'umi';

import { formatMessage } from '@/locales/index';

import styles from './index.less';

const formItemLayout = {
  labelCol: {
    span: 5,
    offset: 3,
  },
  wrapperCol: {
    span: 16,
  },
};

const Step1 = ({ data, setData, next }) => {
  const [form] = Form.useForm();

  const handleSubmit = e => {
    e.preventDefault();
    form.validateFields().then(values => {
      setData(data => ({
        ...data,
        appId: values.appId,
        templateId: values.appId !== data.appId ? '' : data.templateId,
        applyReason: values.appId !== data.appId ? '' : data.applyReason,
      }));
      next(1);
    });
  };

  return (
    <>
      <Card bordered={false} className={styles.fristStep}>
        <Form
          form={form}
          {...formItemLayout}
          labelAlign="left"
          colon={false}
          style={{ width: 762, margin: '0 auto' }}
        >
          <Form.Item
            name="appId"
            label={formatMessage('template.from.appId.label.ID')}
            rules={[
              {
                required: true,
                message: formatMessage('template.from.appId.rule'),
              },
            ]}
          >
            <Input
              style={{ width: 394 }}
              placeholder={formatMessage('template.from.appId.rule')}
              disabled
            />
          </Form.Item>
        </Form>
      </Card>
      <div className={styles.footer}>
        <Space className={styles.backbtn}>
          <Button
            onClick={() => {
              history.goBack();
            }}
          >
            {formatMessage('common.text.back')}
          </Button>
          <Button type="primary" onClick={handleSubmit}>
            {formatMessage('common.text.next')}
          </Button>
        </Space>
      </div>
    </>
  );
};

export default Step1;