低代码在EHR领域中的实践 - 表格设计

在上一篇文章《低代码在 EHR 领域中的实践 - 表单设计》中介绍了飞轮低代码平台的表单设计,表单作为飞轮低代码平台的核心承载了众多业务。相比较表单,表格的业务逻辑性虽然不强,但也是飞轮低代码平台产出频率最高的物料,经过一年多的业务演练,我们将飞轮低代码中的表格制定成了如下统一的功能形态:

1644809013(1).jpg

为了满足不同的业务需求,表格支持了以下几个模块配置:

  • 表格标题
  • 外显搜索栏
  • 搜索框
  • 菜单区按钮
  • 操作区按钮
  • 多选
  • 字段

1644809056(1).jpg

接下来给大家介绍表格的几个核心设计。

1. 字段设计

表格中的字段由数据模型而来,具备了自动数据加载和存储的能力。对于一些直接影响用户操作的字段属性,是依附在信息集中进行设置的,而不强绑定在字段上。这么做的目的是为了支持相同的字段在不同的业务中需要表现出不一样行为的需求。为此,飞轮低代码平台根据现有的EHR业务设计了属于表格的字段属性

  • 查看页显示:控制字段在表格中是否显示
  • 可排序:控制字段在表格中能否排序
  • 可筛选:控制字段能否通过搜索框进行组合筛选
  • 可外显查询:控制字段是否在外显搜索栏显示
  • 可模糊查询:控制字段能否通过搜索框进行模糊查询
  • 排序规则:控制字段在表格中默认是以正序还是倒序的规则进行排列
  • 排序优先级:控制字段设置的排序规则的优先级,优先级越小的(除了0)字段,列表优先按照该字段的排序规则排序
  • ...

可视化编辑器提供了两种字段配置的方式,一种是全量配置:

1644809108.jpg

另一种是单个配置:

1644809132(1).jpg

其中,【查看页显示】、【可排序】两个属性将会在表格渲染的数据模型中体现,而【排序规则】、【排序优先级】则由后端按照相应的配置将数据排序好返回。以上图的配置为例,产出的数据模型为:

{
  fieldList: [ // 表头渲染
    {
      component: "el-input-number", // 字段对应的控件类型
      entityId: "1318069337380741121", // 实体 id
      fieldCode: "F9051", // 字段 code
      fieldName: "年龄", // 字段名称
      isShow: true, // 查看页显示
      sortable: true, // 可排序
      options: [] // 过滤选项
    },
    // ...
  ],
  itemList: [ // 数据渲染
    {
      dataList: [
        {
          entityId: "1318069337380741121", // 实体 id
          fieldCode: "F9051", // 字段 code
          value: "24", // 字段值
        },
        // ...
      ],
      rootEntityDataId: "1325716556984475649" // 根实体 id
    },
    // ...
  ],
  page: { // 页码渲染
    currentPage: 1,
    pageSize: 20,
    total: 168, 
    totalPages: null
  }
}
复制代码

【可筛选】、【可外显查询】、【可模糊查询】三个属性另外在搜索渲染的数据模型中体现。以上图的配置为例,产出的数据模型为:

[
  {
    component: "el-input-text", // 字段对应的控件类型
    fieldCode: "F00719", // 字段 code
    fieldName: "姓名", // 字段名称
    fieldDefaultSearch: true, // 可模糊查询
    filterable: true, // 可筛选
    outerShow: false, // 可外显查询
    fieldCompareList: [ // 关系符
      {
        label: "等于",
        value: "10"
      },
      // ...
    ]
  },
  // ...
]
复制代码

有一些核心概念不理解的,可以先阅读《低代码在 EHR 领域中的实践 - 架构设计与规划》

2. 搜索设计

我们为表格设计了组合筛选、模糊搜索、外显搜索三种搜索方式。

2.1 组合筛选

组合筛选是在EHR领域中提炼出来的一种更强大更精准的搜索方式,核心功能是根据字段绑定的控件类型,渲染对应的关系符选项以及判断值控件,用户则可以自由组合多个关系条件来筛选数据。

1644809206(1).jpg

飞轮低代码平台内部维护了一套控件类型和关系符的对应表:

{
  'el-date-picker-date': [ // 时间选择器
    {
      value: '10',
      label: '等于'
    }, {
      value: '11',
      label: '不等于'
    }, {
      value: '5',
      label: '大于'
    }, {
      value: '51',
      label: '大于等于'
    }, {
      value: '4',
      label: '小于'
    }, {
      value: '41',
      label: '小于等于'
    }
  ],
  'el-switch': [ // 开关
    {
      value: '10',
      label: '等于'
    }, {
      value: '11',
      label: '不等于'
    }
  ],
  ...
}
复制代码

只有将字段配置成【可筛选】,才能让字段出现在组合筛选条件中:

image.png

2.2 模糊搜索

用户可以在不局限于特定条件下进行搜索,但实际上也是通过字段配置才让模糊搜索生效,一般只会将输入型的字段配置成【可模糊搜索】,比如【姓名】:

image.png

2.3 外显搜索

外显搜索是为了解决搜索框组合筛选步骤多、模糊搜索精准差的问题。表格会根据具有【可外显查询】属性的搜索字段来渲染外显搜索栏,没有【可外显查询】属性字段则不渲染外显搜索栏。不同于搜索框是表格具有的默认功能,外显搜索还可以通过配置来决定是否启用:

image.png

在某些业务下,表格需要默认根据某个或者某几个字段的值进行筛选(默认值会在外显搜索栏中展示),默认值可能是固定的静态数据也可能是运行时动态生成的数据,可以在【默认筛选规则】中进行配置:

1644809340(1).jpg

其中【规则类型】决定了默认值是静态还是动态:

  • 静态筛选就是在判断值中选择一个默认筛选值;
  • 动态筛选则需要填写后端约定好的接口,默认筛选值将由后端计算出来。比如一个表格需要默认根据当月的时间来筛选,每个月的时间是动态的,则需要配置接口返回当月的时间。

还有一种情况就是,业务需要有个默认搜索值,但是不允许用户进行修改,这时可以在配置默认筛选规则的前提下,将外线搜索框设置为隐藏。

2.4 搜索传参

为了区别用户使用了哪种搜索方式进行搜索,前后端约定了如下传参格式:

  • 组合筛选
{
  andQueryList: [
    {
      compareType: "", // 关系符
      fieldCode: "", // 搜索的字段编码
      fieldValue: "", // 搜索的字段值
      querySource: "dropDown" // 表示组合筛选
    },
    ... // 多个
  ]
}
复制代码
  • 模糊搜索
{
  andQueryList: [
    {
      orQueryList: [
        {
          compareType: "", // 关系符,值为空
          fieldCode: "", // 搜索的字段编码
          fieldValue: "", // 搜索的字段值
          querySource: "fuzzy" // 表示模糊搜索
        },
        ... // 需要将所有支持模糊搜索的字段携带模糊搜索的值传给后端
      ]
    }
  ]
}
复制代码
  • 外显搜索
{
  andQueryList: [
    {
      compareType: "", // 关系符,值为空
      fieldCode: "", // 搜索的字段编码
      fieldValue: "", // 搜索的字段值
      querySource: "default" // 表示是外显搜索
    },
    ... // 多个
  ]
}
复制代码

为了防止搜索条件冲突,我们将这三种搜索方式的关系设计为互斥,即使用任何一种搜索方式都会清空其他两种搜索方式的搜索条件。

3. 按钮设计

我们为按钮设计了基本、高级、动作三种类型的配置。

1644809424(1).jpg

3.1 基本配置

主要针对不同的按钮类型进行按钮样式配置。

1644809443(1).jpg

完整的配置关系如下图所示:

1644809462(1).jpg

对于标准类型的按钮,飞轮低代码平台内置了几个常用的按钮样式(只是样式,不涉及逻辑),一方面为了让配置者能够快速的配置常用按钮样式,减少常用按钮样式的配置负担;另一方面是为了统一常用按钮的样式,培养配置者的惯性样式思维。比如,我们不希望【删除】按钮在不同的业务中展示不同的样式。

3.2 高级配置

配置按钮的名称、样式、禁用、隐藏属性根据某个字段值进行动态的改变。

1644809495(1).jpg

比如,我们将列表中性别为【女】的数据设置为不可编辑:

1644809516(1).jpg

产出的协议为:

{
  name: "", // 按钮名称
  type: "", // 按钮样式
  disable: [{ // 禁用配置
    compareType: "10", // 关系符
    fieldCode: "F00370", // 字段编码
    fieldValue: "2", // 字段判断值
    result: true // 结果
  }],
  hide: "" // 隐藏配置
}
复制代码

在业务中渲染为:

1644809545(1).jpg

3.3 动作配置

配置页面的交互操作,比如跳转、打开弹窗、请求等,都可以视作按钮的动作。

1644809563(1).jpg

动作配置是按钮设计最复杂的部分,复杂之处在于按钮动作不支持代码的编写,而是用枚举的方式来实现一个完整动作的生命周期。完整的配置关系如下图所示:

1644809609(1).jpg

通过分析归类,最后沉淀了6个左右的动作类型,每一个动作类型最终本质上都是对应一段执行函数。我们将这些动作类型函数集中放在了一个文件中进行管理,代码简化如下:

// button-actions.js
export default class ButtonActions {
  constructor (_this) {
    this.vm = _this // vue 实例
    this.button = null // button 对象
    this.data = null // 行数据
  }
  
  execute (button, data) {
    this.button = button
    this.data = data
    const { actionType } = this.button
    switch (actionType) {
      case '1': // 跳转
        this.goToPage()
        break
      case '2': // 打开弹框
        this.openDialog()
        break
      case '3': { // 发送请求
        const { requestMode, requestUrl, requestType } = button
        this.handleRequest(requestMode, requestUrl, requestType)
        break
      }
      case '4': // 打开抽屉
        this.openDrawer()
        break
      case '5': // 删除
        this.handleDelete()
        break
      case '6': // 消息确认
        this.openConfirmDialog()
        break
      // ...
    }
  }
  
  async goToPage () {}
  
  openDialog () {}
  
  openDrawer () {}
  
  handleRequest () {}
  
  handleDelete () {}
  
  // ...
}
复制代码

使用时,代码简化如下:

// LowCodeTable.vue
<script>
import ButtonActions from '../button-actions'

export default {
  mounted () {
    this.instance = new ButtonActions(this)
  },
  methods: {
    handleButtonClick (button, data) {
      this.instance.execute(button, data)
    }
  }
}
</script>
复制代码

3.4 传参配置

为了减少用户的配置负担,按钮行为中内置了很多默认参数,但仍是避免不了有些行为需要额外的参数。为此,我们设计了两种额外参数传递的方式:

  • 控件传参

主要针对动作类型为弹窗/抽屉,且目标对象为控件的行为。因为,控件大多数为自定义物料,是针对某项业务而特殊开发的组件,按钮行为中默认的参数往往满足不了其依赖的参数。所以,我们还需要支持配置者对控件需要的额外参数进行配置:

1644809708(1).jpg

控件参数的格式为json字符串格式:

{
  "type": 1,
  "rootEntityDataId": "{rootEntityDataId}",
  ...
}
复制代码

其中用{} 包裹的表示动态变量,上面例子中的rootEntityDataId将会动态的获取低代码引擎中的rootEntityDataId值。

  • 请求传参

支持配置请求URL地址,那肯定要支持配置额外的请求参数。为了减少过多的变量定义,我们并没有增加额外的参数配置选项,而是将额外参数配置在请求URL地址上来进行传递:

/aaa/bbb/?rootEntityDataId={rootEntityDataId}&type=0
复制代码

低代码引擎会将?后面的参数解析成与控件参数一样的json格式。有一点要注意,尽量让请求方式改为post

4. 结尾

由于目前EHR业务的需求,我们的表格暂不支持行内编辑,也不支持行内组件render功能,表格只是一个纯文本展示的形态,所以没有太多关于表格内容区域配置的设计。同时,由于目前我们的飞轮低代码主要针对EHR这个垂直领域,没有支持一些定制化的样式编辑,比如字体大小、内外边距、按钮形态等,支持这些属性编辑不难,但是我们不想增加过多的配置负担。

文章没有对我们的低代码表格做过多代码层面上的讲解分析,核心思想是想表达我们在低代码体系中对表格的配置设计思想。希望能给大家在做低代码开发的时候带来一些灵感,也希望能与大家一起交流我们的设计思想,给我们也提一些建议。

猜你喜欢

转载自juejin.im/post/7069944538088865799