## fieldMap
存放表单中每一个表单域的 type 和组件的映射关系。如：
|表单域type|对应组件|描述
|--|--|--
|SingleTextInput|MkInput|单行文本输入框
|ExpenseTypeInput|ExpenseTypeInput|费用类型选择组件
|OptionInput|{ MANUAL: 'MkSelect', DataSource: 'OptionInput'}|选项组组件。选项组的选项分为手动输入和数据源导入。Manual对应手动输入情况下的选项组组件，DataSource对应数据源导入情况下的选项组组件
|CityInput|{ SINGLE: 'CityInput', PAIR: 'CityPairPicker' }|城市选择组件。城市组件分为单个城市和起止城市两种模式。Single对应单个城市的组件，PAIR对应起止城市模式的组件。

## FormDish
主要用来进行表单域的渲染。
根据 fieldMap 中的映射关系，映射出对应的组件。并传入相应的props，设置相应的校验规则

### 高阶组件 
接收两个参数 WrapperComponent 和 options，返回由 WrapperComponent 包裹着的 node, options 作为 props 传入 WrapperComponent 中使用。
WrapperComponent 主要用于显示组件的 label、错误信息等，web 端可直接传入 antd 的 Form.Item
```
function enhanceFormItem(WrapperComponent, options) {
  const node = getFieldDecorator(identifier, { rules })(
    <Field
    fieldPropertys={property}
    fieldProps={fieldProps}
    extraProps={extraProps}
    disabled={disabled}
    readOnly={readOnly}
    />
  );
  return WrapperComponent ? (
    <WrapperComponent
      field={field}
      form={form}
    >
      {node}
    </WrapperComponent>
  ) : node 
}
```
### props传值
- property 为表单 scheme 中相应的设置，包括 placeholder、required、label、webSize等。
- extraProps：自定义props，有其他业务逻辑需要传入 Field 中的 props

***表单域经过 antd 中 Form.create() 处理后的表单具有自动收集数据并校验的功能，会自带 this.props.form 的属性。getFieldDecorator 用于和表单进行双向绑定，不用显式的传入 value 和 onChange。***
```
// FormDish 组件接收的 props
// setFieldMap 用于设置组件与schema 中 type 的映射关系
// setValidator 用于设置自定义校验方法
<FormDish
    field={field}
    publicProps={publicProps}
    privateProps={privateProps}
    form={form}
    setFieldMap={setFieldMap}
    setValidator={setValidator}
/>
```
FormDish 代码实现
```
// extraProps
generatetProps = () => {
  const {
    publicProps = {},
    privateProps = {},
    form,
    field,
    ...restProps
  } = this.props;
  let props = {
    ...publicProps,
    ...privateProps,
    ...restProps
  };
  return props;
}
// fieldProps
filterFieldProps = () => {
  // 若需要 field 中的 type, identifier 等作为props，可在此返回
  // const { field: { type } } = this.props;
  return {};
}
generateNode = () => {
    const { 
    field: { type, identifier }, 
    form: { getFieldDecorator } 
  } = this.props;
  const { property } = field;
  const Field = fieldMap[type];
  const extraProps = this.generatetProps();
  const fieldProps = this.filterFieldProps();
  const rules = this.generatetRules();
  return getFieldDecorator(identifier, {
    rules
  })(
    <Field
      {...property}
      {...fieldProps}
      extraProps={extraProps}
    />
  )
}
render() {
    const { field: { property } } = this.props;
  const { isFieldHide } = property;
  return isFieldHide ? null : this.generateNode()
}
```
### validator
通过 setValidator 方法返回组件所需的所有自定义校验方法，方法命名规则为 `validate${type}`，如下：
```
export default {
    validateRatioInput: validateNumericalValue,
    validateAmountInput: validateNumericalValue,
    validateMoneyAdjust: validateNumericalValue,
    validateDateTimeInput,
    validateCityInput,
    validateAccountInput,
    validateCollectionAccountInput: validateAccountInput,
    validateInvoiceInput,
    validateTableInput: validateDetailTable
};
```
在 generateRules 中，同样通过 type 来匹配相应的校验方法
```
const rules = [];
const rule = { required };
if (this.validators[`validate${type}`]) {
  rule.validator = this.customValidator;
}
rules.push(rule);
```