LowCode - 可视化中的规则组件设计

5,091 阅读3分钟

🌈 规则组件示例

image.png

☀️ 为什么需要规则组件

数据可视化平台底层JSON解析器提供了模板字符串的支持,例如:

'#{data.count > 10 ? "red" : "yellow"}'

在可视化搭建中,模板字符串使用并不友好:

  1. 用户需要学习模板字符串语法,并且在编辑器中编写模板字符串并不方便
  2. 变量名需要手动编写,容易出现错误

🌧 设计要求

凡是模板字符串能够实现的,规则组件要全部实现。

  1. 单一变量结果,如#{data.count}
  2. 条件判断,如'#{data.count > 10 ? "red" : "yellow"}'
  3. 多条件判断,如#{data.count > 10? "red" : data.price > 100 ? "yellow" : "blue"}
  4. 同时满足多个条件,如#{data.count > 10 && data.price > 100 ? "red" : "yellow"}

🌟 设计思路

整体思路

模板字符串拿到的结果是唯一的,即当前条件满足后使用该结果,不满足条件继续向后判断。

可以设计成数组的格式:

[
  { conditions: conditions1, result: 'result1' },
  { conditions: conditions2, result: 'result2' },
  { result: 'result3' }
]

数组中每组元素是关系,当前条件满足后,使用该组结果,无需向后判断。

有的组不需要条件判断,默认满足,则不需要设置conditions。

如此满足设计要求1,2,3.

conditions思路

为方便构成data.count > 10的结构,conditions由三个字段组成: 变量(variable) 、比较符(operator)、比较值(value)。

conditions: { variable: 'data.count', operator: '===', value: 10 },

为了满足多条件(设计要求4),同样将conditions设计成数组格式,每组元素是关系,需同时满足。

conditions: [
 { variable: 'data.count', operator: '===', value: 10 },
  { variable: 'data.price', operator: '>', value: 100 }
],

☃️ 格式解析

组件的Json格式定好后,就要考虑格式转换了。

借助内置的模板字符串解析函数template,获取condition执行结果:

function transformValue(value) {
  if (typeof value === 'string') {
    return `'${value}'`;
  }

  return value;
}

function parseCondition(condition, data) {
  const { variable, operator, value } = condition;
  const conditionStr = operator
    ? `#{${variable} ${operator} ${transformValue(value)}}`
    : `#{${variable}}`;

  let result;
  try {
    // 把data传入模板字符串,返回模板字符串执行结果
    result = template(conditionStr, data);
  } catch (e) {}

  return result;
}

其他的只要按照设计思路编写代码就好

 function transform(config, data) {
  let finalResult;
  for (let i = 0; i < config.length; i += 1) {
    const { conditions = [], result } = config[i];
    if (!conditions.length) {
      finalResult = result;
      break;
    }
    if (conditions.every((condition) => parseCondition(condition, data))) {
      finalResult = result;
      break;
    }
  }

  return finalResult;
}

🌈 代码实现思路

数组配置能力

整体基于rc-field-formList组件实现,为了美化样式增加左侧连接线。

连接线

原理:每组元素以中心为基准绘制向上向下的两条线,隐藏首元素向上的线和末元素向下的线即可。

代码实现:github

result结果项配置

为方便管理和编写代码,整体采用JSON化配置方式实现。示例中代码使用如下结构:

resultFields: [
  {
    name: 'children',
    label: '文本',
    wrapperCol: 24,
    labelCol: 2,
    field: {
      type: 'autocomplete',
      props: {
       allowClear: true,
      }
    }
  },
  {
    name: 'type',
    label: '类型',
    field: {
      type: 'autocomplete',
      props: {
        source: [
          { text: 'success', value: 'success' },
          { text: 'danger', value: 'danger' },
        ],
        resultType: 'textType',
      },
    },
  },
  {
    name: 'style',
    label: '样式',
    field: 'editor',
  }
]

实现原理可以参考这篇文章:sula-插件实现

// 核心代码如下
import { FunctionComponent, ComponentClass } from 'react';

class PluginStore {
  plugins = {};

  registerField = (key, field) => {
    if (this.plugins[key]) return;
    this.plugins[key] = field;
  };

  getPlugins = () => {
    return this.plugins;
  };
}

const pluginStore = new PluginStore();

export default pluginStore;

👀 结束

插个广告:

前端配置化框架 - sula