浏览本文之前,倡议先浏览往期内容:基于 Formily 的表单设计器实现原理剖析 和 Form Schema 定义详解。

表单是前端常见的交互模式,宽泛用于业务数据收集的场景中。例如增加员工时填写的员工信息表,申请固定资产时填写的申请表等。借助表单引擎,开发者能够疾速实现上述表单的设计和公布,晋升企业管理效率。

JSON Schema

JSON Schema 是表单设计器和表单渲染组件之间的沟通语言,是一个 JSON 文件协定,用于标准 JSON 文件内容。它与平台无关,能够形容任意简单的数据结构。JSON Schema 在 JSON 的格局上,退出了一些列的标准化属性,用于形容结构化数据。

全象云平台表单设计器的输入是一份形容表单字段的 JSON Schema,表单设计实现后 JSON Schema 将间接存储到后端。表单公布后,前端再依据 JSON Schema 渲染表单。

Schema 的简化定义

此处是 Schema 的简化定义,具体定义请浏览 Form Schema 定义详解。

interface Schema {  fields: Record<FieldKey, FieldSchema>;}interface FieldSchema {  title: string;  type: 'string' | 'object' | 'array' | 'number' | 'boolean';  component: string;  componentProps: {    [name: string]: any;  };}

在下面的类型定义中:

  • FieldKey 是字段在表单中的惟一标识,用户侧不透出。
  • title 示意表单中字段对应的 label,它的值用户可读。
  • type 示意组件承受和冀望返回的数据类型。
  • component 示意该字段用什么 input 组件渲染。
  • componentProps 示意传给组件的 props,用于管制组件的行为。

表单数据展现

全象云平台表单设计器目前提供了根底字段、高级字段、布局字段等 21 种组件,开发者应用这些组件能够疾速搭建表单。

  • 根底字段:单行文本、多行文本、单选框、复选框、数字、工夫日期、下拉单选框、下拉复选框。
  • 高级字段:子表单、关联记录、人员选择器、部门选择器、附件、图片、级联抉择、统计、流水号、关联数据。
  • 布局字段:栅格、分组、选项卡。

通过 FormDataValueRenderer() 办法,将存储到服务器的 JSON Schema 和 value 渲染出表单。

FormDataValueRenderer 实现

不同类型的字段须要不同的展现模式,例如,展现根底字段时只须要显示 value 值即可;展现子表单时,须要将数据显示为表格;展现附件时,须要将附件显示为文件模式;展现图片时,须要将图片显示为缩略图。

简单构造表单数据展现采纳的是策略模式,依据 field schema 的 component 属性,采纳不同的策略解决显示到 web 页面。

以下是 FormDataValueRenderer 对于不同字段组件的解决。

export default function FormDataValueRenderer({ value, schema, className }: Props): JSX.Element {  switch (schema['x-component']?.toLowerCase()) {  case 'subtable':    return (<SubTableValueRenderer schema={schema} value={value} />);  case 'associatedrecords':    return (<AssociatedRecordsValueRender schema={schema} value={value} />);  case 'associateddata':    return (<AssociatedDataValueRender schema={schema} value={value as LabelValue} />);  // others components   default: {    const content = getBasicValue(schema, value);    return (      <span title={typeof content === 'string' ? content : ''} className={className}>{content}</span>    );  }  }}

其余字段值的转换

除开非凡的字段,对于其余字段,仅仅须要以字符串的模式展现值,上面是对于字段值的转换:getBasicValue()

export function getBasicValue(schema: ISchema, value: FormDataValue): string {  switch (schema['x-component']?.toLowerCase()) {  case 'input':  case 'textarea':  case 'radiogroup':  case 'select':  case 'serial':    return value as string;  case 'numberpicker':    return numberPickerValueRender({ schema, value });  case 'checkboxgroup':  case 'multipleselect':    return stringListValue({ schema, value });  case 'datepicker':    return datetimeValueRenderer({ schema, value });  case 'associateddata':  case 'cascadeselector':  case 'userpicker':  case 'organizationpicker':    return labelValueRenderer(value);  case 'aggregationrecords':    return statisticValueRender({ schema, value });  default:    logger.warn('encounter unsupported formDataValue:', value, 'schema:', schema);    return value?.toString();  }}

1、单行文本、多行文本、单选框、下拉框、流水号返回 value。

2、数字字段 value 须要解决到开发者设置的准确位数。

function numberPickerValueRender({ schema, value }: ValueRendererProps): string {  return Number(value).toFixed(schema?.['x-component-props']?.precision || 0);}

3、关联记录、级联抉择、人员选择器、部门选择器 value 转换成字符串格局。

export function labelValueRenderer(value: FormDataValue): string {  if (Array.isArray(value)) {    const labels = (value as FormBuilder.Option[]).map(({ label }) => label).join(', ');    return labels;  }  return (value as FormBuilder.Option)?.label;}

4、统计须要将 value 依照统计规定,进行统计计算后返回后果。

function statisticValueRender({ schema, value }: ValueRendererProps): string {  const { decimalPlaces, roundDecimal, displayFieldNull } = schema['x-component-props'] as {    decimalPlaces: number, roundDecimal: RoundMethod, displayFieldNull: string  };  let method = Math.round;  if (roundDecimal === 'round-up') {    method = Math.ceil;  } else if (roundDecimal === 'round-down') {    method = Math.floor;  }  return method(parseFloat(value as string)).toFixed(decimalPlaces) + '' || displayFieldNull;}

总结

本文咱们从 Schema 的定义,到不同字段的展现实现,最终实现了简单构造表单数据的展现性能。不过还有很多须要依据不同业务需要进行具体分析的场景,须要大家在理论业务中去进一步提炼。

公众号:全象云低代码
GitHub:https://github.com/quanxiang-...