理解 Enhancer 变量体系

Enhancer 平台之所以能快速地满足各类信息系统的开发,其中一个重要的原因是,它有一套完备的变量体系,方便开发者直观地使用。本文来讨论下平台的变量体系。

1. 常规业务系统增删改查中的数据流

dataflow

一个常规的业务系统,最终都会由后台做 IO 来访问或者持久化数据。在具体的关系数据库中,这种 IO 操作体现在将各种来源的数据汇集成 SQL 增删改查操作,如上图。 于是我们可以设计一套规范的数据来源和数据组织方式,让开发者按照该预定机制,直观快速地取用到各类数据,完成相关业务逻辑的开发。Enhancer 的变量体系就是这样一种方便开发者的机制。

2. Enhancer 的变量命名规则

服务端变量: 单词[.单词],如:USER_ID,SYS.PATH。

客户端变量: 数字-单词[.单词],如:1-USERNAME,12-USER_NAME,11-COMPONENTS.AMOUNT

注:以上 [] 表示可重复 0 次和多次的子结构。

JS 正则表达式为:

服务端变量: /^\w+(.\w+)*$/

客户端变量: /^\d+-\w+(.\w+)*$/

推荐在书写时全部采用大写。

3. Enhancer 的变量分类

3.1 服务端变量

服务端变量指变量值的存放和使用只能在服务端的数据变量。又分为:

【系统变量】

指从启动到运行由自身产生,表现系统状态的一些变量,比如 PATH(启动路径), CURR_TIME(当前系统时间),CURR_DATE(当前系统日期),CURR_MONTH(当前月份),LAST_YEAR(去年),NEXT_MONTH(下个月)等。

命名规则 单词[.单词]

【用户变量】

指从用户登录到退出,属于该用户的数据变量,如 USER_ID(用户 ID),USER_NAME(用户名), ROLES(角色), GENDER(性别), DEPARTMENT(所属部门) 等。

命名规则 单词[.单词]

3.2 客户端变量

客户端变量指客户端产生的数据变量,有以下几类

【窗口变量】以窗口被编号开头命名,窗口编号一定大于 10

通过用户的操作产生的表现当前窗口各种状态的数据变量,不同窗口包含的组件类型(查询器,表单,树…)不同,其组织变量的方式也不同,比如在查询组件窗口中用户选择了某数据行,此时该窗口可能有这些变量:11-STU_NO(11 号窗口当前选中行的学号列值), 11-SELECTED_ROWS_COUNT(11 号窗口选中的行数),再比如在树组件中用户选择某个节点:12-LAST_SELECTED_NODE_VALUE(12 号窗口当前选中节点的值),- 12-LAST_CHECKED_LEVEL(当前选中节2. 点的层级) 等等。

命名规则 窗口编号-单词[.单词]

【系统初始变量】以 0 开头命名

由服务器端注入到前端的可用变量,如 0-CURR_YEAR(当前系统年份如:2018), 0-CURR_DATE(当前系统日期如:16),0-CURR_MONTH(当前系统月份如:8)。

命名规则 0-单词[.单词]

【用户初始变量】以 1 开头命名

由服务器端注入给前端使用的关于当前用户的变量,如1-USER_ID(当前用户 ID),1-USER_NAME(当前用户名),1-ROLES(当前用户的全部角色)。

命名规则 1-单词[.单词]

【用户行为变量】以 2 开头命名

系统记录用户操作行为的数据变量,如下表:

变量名含义
2-LAST_CLICKED_BTN_IDButtonClick1上一次点击的按钮 ID 编号
2-CURR_PAGE_ID159当前页面编号
2-PREV_PAGE_ID155上次浏览的页面编号
2-LAST_EVENT_ID159-w12-ButtonClick1上一次点击按钮ID
2-LAST_EVENT_SRC_ID159-w12上一次触发事件所属窗口 ID
2-LAST_EVENT_SRC_NO12上一次触发事件所属窗口编号
2-LAST_PROCEDURE_RESULT{success: true, data: {…}, messge: "执行成功"}上一次提交后台过程返回的结果

命名规则 2-单词[.单词]

【当前页面 url 查询参数变量】以 3 开头名命

3-PARAM1 表示 url?param1=val1&params2=val2 查询参数 param1 的值 'val1'。

命名规则 3-单词[.单词]

【上一页面内的窗口变量】以 8 开头命名

8-12_STU_NO 表示上一页面 12 号窗口的学生编号。

命名规则 8-窗口编号_单词[.单词]

【当前页面由外部传递的数据】以 9 开头命名

9-ARTICLE_ID 表示从外部传递给当前页面的文章 ID 号。使用脚本 Enhancer.openPage(页面编号, 数据) 可以在打开页面时传递数据。例如:Enhancer.openPage(123, {article_id, '9187324'})。那么此时 变量@9-ARTICLE_ID@的值是 9187324。

命名规则 9-单词[.单词]

4 变量的用法

4.1 用在 SQL 中 (使用变量引用符号: @变量@)

  • 在查询语句中
  1. SELECT * FROM TAB_A a, TAB_B b
  2. WHERE a.id = b.id AND a.code = @12-CODE@ AND b.user_id = @USER_ID@
  • 在非查询语句中(事件触发执行后台 SQL)
  1. UPDATE accounting_document
  2. SET accounting_date = @14-ACCOUNTING_DATE@,
  3. attachment_num = @14-ATTACHMENT_NUM@
  4. WHERE id = @11-ID@;
  • 用作 SQL 中的表名字段名,需使用$变量$强化转义规则,防止注入攻击
  1. SELECT * FROM $12-TABLE_YEAR$
  2. WHERE field1 = @15-VARNAME@ AND $12-FIELD_NAME$ = @12-USER_INPUT@

4.2 用在组件数据绑定中

最常见的是给表单的某个输入域绑定其他窗口变量。

4.3 用在条件表达式中

在配置事件动作执行条件时(双击流程图中的动作线),可书写变量以精确控制动作是否执行,如:

  1. @11-GENDER@ = '男' AND @11-CHECKED@ = true

4.4 用在前端脚本中

如在事件设置中配置执行-事件触发时脚本来控制后续动作是否继续执行:

  1. var gender = @11-gender@;
  2. var cnt = @12-selected_rows_count@
  3. if (cnt > 5 || gender == '女') {
  4. alert('仅限女,且数量不超过 5 个')
  5. return false
  6. }

4.5 用在后台过程执行中【选修】

如在事件设置中配置 执行-服务器过程—> JavaScript 过程

  1. var sql = `UPDATE student SET name = ?, birthday = ?, birth_place = ?, gender = ?, phone = ?,
  2. nation = ?, entry_year = ?, ssn = ?, family_address = ?, political_status = ?, school_year_length = ?
  3. WHERE student_no = ?`;
  4. // 直接 @变量@ 从页面取用本次过程执行需要的数据。
  5. var params = [@12-NAME@, @12-BIRTHDAY@, @12-BIRTH_PLACE@, @12-GENDER@, @12-PHONE@, @12-NATION@,
  6. @12-ENTRY_YEAR@, @12-SSN@, @12-FAMILY_ADDRESS@, @12-POLITICAL_STATUS@, @12-SCHOOL_YEAR_LENGTH@,
  7. @12-STUDENT_NO@];
  8. // Enhancer 是全局对象,直接使用。
  9. var databaseService = Enhancer.getDatabaseService();
  10. databaseService.execute(sql, params, function(err, result) {
  11. if (err) {
  12. console.log(err);
  13. // 不论结果执行成功失败,需要调用 done 方法表示本次过程结束。
  14. // done 方法的第一个参数传递系统级 err,第二个参数传递常规结
  15. // 果对象(包含 success 和 message 字段)。
  16. done(null, {
  17. success: false,
  18. message: '操作失败操作失败。' + err.message
  19. });
  20. return;
  21. }
  22. done(null, {
  23. success: true,
  24. message: '修改成功!'
  25. });
  26. });

5 给用户注入其他初始变量

在默认情况下,系统表示用户状态的可用变量只有 USER_NAME, USER_IDROLES。有时候我们需要用户其他相关信息,比如性别生日职位所属部门账号状态等等,希望他们随着用户的登录,由系统保存为可用的用户变量,方便开发时使用,则可以通过以下方式为用户添加初始变量:

  • 使用绑定用户表方式登录时

此时,只需给该登录用户表添加需要的任何字段,系统会在用户登录成功时,将该用户记录其他字段全部添加为初始变量(PASSW0RD 除外),开发时可随意引用。例如用户表有字段名叫 department, 那么在服务端使用 @department@ 或者在客户端使用 @1-DEPARTMENT@ 便可引用到该变量值。

此外,还可以在【登录校验后函数】中查询当前用户相关的其他数据,然后调用 user.setVariables 方法,给当前用户赋予其他初始变量。也可以根据用户表的相关状态字段控制登录,如:

  1. function (enhancer, user, done) {
  2. // ...
  3. if (user.getVariable('STATUS') !== 1) {
  4. done(null, '您的账号已被禁用,请联系管理员。');
  5. return
  6. }
  7. // ...
  8. }
  • 使用自定义校验登录过程时在自定义过程校验完毕之后,可以调用 user.setVariables 方法来给该用户设置初始变量,如:
  1. function (enhancer, user, done) {
  2. // 完成 用户校验之后,可能再次异步请求获得了一些 用户的数据
  3. // 设置用户初始变量
  4. user.setVariables({
  5. field1: value1,
  6. field2: value2
  7. ...
  8. });
  9. done(null, true);
  10. }

之后便可以在服务端或者客户端使用变量 @FIELD1@, @1-FILED1@, @FIELD2@, @1-FILED2@ …

【说明】在线上开发调试阶段,由于没有一个真实的系统启动过程和用户登录过程,所以相关变量需要手工在预览界面顶部工具栏进行【变量设置】。开发者可以任意调整其值,来做不同场景的测试。项目发布之后,这些变量会按照预定机制赋予真实值。[必修]理解Enhancer变量体系(17分钟)  - 图2

正确把握了 Enhancer 变量的概念,对于业务的拆解设计会起到事半功倍的效果。

【附】系统预设可用变量列表