写点什么

JSON Schema 实现复杂结构表单数据展示

  • 2022 年 3 月 21 日
  • 本文字数:2583 字

    阅读完需:约 8 分钟

JSON Schema 实现复杂结构表单数据展示

阅读本文之前,建议先阅读往期内容:基于 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-cloud/quanxiang

发布于: 刚刚阅读数: 2
用户头像

还未添加个人签名 2021.08.23 加入

一个持续分享硬核技术(包含前端、后端)的团队,欢迎关注呀! 公众号:全象云低代码 GitHub:https://github.com/quanxiang-cloud/quanxiang

评论

发布
暂无评论
JSON Schema 实现复杂结构表单数据展示_前端_全象云低代码_InfoQ写作平台