# expression - 表达式扩展

在实际项目中,需要通过扩展表达式函数,封装一些业务逻辑,并在不同的地方调用。如:

  1. 将部门和用户的个性化权限保存在其他表中,然后通过脚本函数获取部门、用户的权限(门户、表单、spg中都会调用)。
  2. 在不同的位置大量的使用相同的表达式块来做计算。使用表达式扩展来将这些相同的表达式块抽取成一个自定义的表达式函数,在需要使用的位置直接调用该函数即可。
  3. 抽取一段SQL定义成表达式函数。该自定义函数可以在模型或者仪表板中的计算字段中使用,并在编译表达式生成SQL的时候会将函数替换成定义的SQL。支持针对不同的数据库实现不同的SQL模板。

本文讲述如何开发一个表达式扩展。

# 扩展文件结构

  1. package.json 定义扩展的配置信息。
  2. main.ts 定义和实现前端扩展函数。
  3. main.action.ts 定义和实现后端扩展函数。
  4. manURL.md 定义帮助文档。

推荐同时实现前端和后端函数,但也可只实现一种,同时实现时,需要确保前后端的函数名相同。

# package.json

package.json描述了扩展的所有配置信息,文件格式符合npm规范 (opens new window)

{
	"name": "succ_expression_security",/**扩展名,和扩展所在的目录同名**/
	"displayName": "扩展权限函数",/**扩展标题**/
	"description": "一个空白的表达式扩展模板",/**扩展描述信息**/
	"version": "1.0.0",/**扩展的版本**/
	"thumbnail": "thumbnail.jpg",/**缩略图名称,可更改,建议用thumbnail.jpg**/
	"compatibilities": {
		"platform": "^4.0.0"
	},
	"author": {
		"name": "YourName",/**发布者信息**/
		"email": "name@xxx.com",
		"homePage": "https://www.succez.com/"
	},
	"categories": [
		"expression"
	],
	"main": "main",
	"contributes": {
		/** 函数定义,参考`ExpFuncInfo` */
		"expressionFunction": [{
			"name": "ext_func", /** 方法名*/
			"desc": "扩展函数", /** 描述 */
			"params": [{
				"name": "参数名",
				"desc": "参数描述",
				"returnType": "String",
				"optional": false,
				"repeatable": false
			}],
			"manURL": "EXPFUNC.md",/** 帮助文档的名字,应该就在扩展中,并且后缀为.md */
			"returnType": "String",
			"group": "others", /** 表达式方法的分组 */
			/** 方法体,可以使用系统中的表达式,以及本身定义的参数 -- 表达式扩展功能2*/
			"expTemplate": "CASE WHEN TONUM(RIGHT(LEFT(userid, 17),1)) % 2 == 1 then '男' ELSE '女' END", 
			"SQLTemplates": [ /** 自定义SQL方法的模板。可针对不同的数据库有不同的实现。 -- 表达式扩展功能3*/
				{
					"dataSource": "MySQL", /**  数据库类型 */
					/** SQL模板,其中?1表示第一个参数,?2表示第二个参数,以此类推,此模板中只能用SQL的原生的语法 */
					"SQLTemplate": "CASE WHEN MOD(cast(LEFT(?1, 17) AS decimal(30,8)), 2)=1 THEN '男' ELSE '女' END " 
				}
			],
		}]
	}
}

TIP

  1. 如功能1:无需定义expTemplateSQLTempaltes。但是要实现对应的main.tsmain.action.ts
  2. 如功能2:只需要定义expTemplate,它是扩展表达式函数的函数体,在函数体中只能引用系统内部的表达式函数。
  3. 如功能3:只需要定义SQLTemplates,它用于描述不同数据库的函数体,在SQLTemplate中只能引用数据库的原生语法。
  4. expTemplateSQLTemplate不能存在于相同name的表达式扩展定义中。

# manURL.md

manURL.md是此扩展的帮助文件,可在系统表达式对话框中显示出来帮助用户使用表达式扩展。名字对应的是package.json中定义的manURL

例如package.json中有如下定义

"manURL": "GENDER.md"

那么对应的帮助文档文件名应该为GENDER.md

# 文件内容

---
permalink: /exp/func/gender
sidebarDepth: 0
---
# **GENDER([*p_id*,] property)**

根据身份证号获取性别

**获取性别**

## 参数

***p_id***:必须,居民18位身份证号。

## 示例

1. `GENDER("420100********1112")` 返回 男,表示男性

# 显示效果

帮助文档显示效果

# main.ts

实现前端扩展函数。

对应的表达式函数实现,必须被export出来,私有函数不要export。 前端函数支持异步计算,可通过返回Promise返回异步结果。


/**
 * 扩展函数xxx
 * 
 * @param context 表达式上下文,可以通过该上下文获取当前用户信息、当前资源等,在不同的场景返回的上下文的实现不同,如在表单中执行扩展脚本时,还可以在上下文中获取
 * @param args 不定参数,也可以分开写。
 * @returns
 */
export function custom_func1(context: IExpEvalDataProvider, ...args: any[]) { // 对外提供的函数
}

export function custom_func2(context: IExpEvalDataProvider, arg0: string, arg1: JSONObjet) { // 对外提供的函数
}

function custom_func3(arg0: string, arg1: JSONObjet) { // 内部私有函数
}

# main.action.ts

实现后端扩展函数,可以定义多个函数,需要支持外部调用的函数需要export。

与前端函数不同,后端函数不支持返回异步结果。


/**
 * 扩展函数xxx
 * 
 * @param context 表达式上下文,可以通过该上下文获取当前用户信息、当前资源等,在不同的场景返回的上下文的实现不同,如在表单中执行扩展脚本时,还可以在上下文中获取
 * @param args 不定参数,也可以分开写。
 */
export function custom_func1(context: IExpEvalDataProvider, ...args: any[]) { // 对外提供的函数
}

export function custom_func2(context: IExpEvalDataProvider, arg0: string, arg1: JSONObjet) { // 对外提供的函数
}

function custom_func3(arg0: string, arg1: JSONObjet) { // 内部私有函数
}

是否有帮助?
0条评论
评论