后端视图扩展
在开发中,常常需要对已有的视图进行扩展,例如增加字段、添加标签页等。以下是一个详细的示例和说明,展示如何通过 JSONPath 对视图进行扩展。
1. 语法示例
{
"jsonpath": [
{
"has_not": "tars",
"expr": "tbar.打印",
"position": "after",
"body": [
{
"action": "create",
"auth": "create",
"name": "无单据生成",
"actionAfter": "refreshTable"
}
]
},
{
"expr": "columns.repairDate",
"position": "before",
"body": [
{
"displayName": "报修单号2扩展",
"name": "reportNo2",
"groupConf": {
"name": "故障信息",
"id": "repairInfoGroup"
}
}
]
},
{
"expr": "buttons.编辑",
"position": "before",
"body": [
{
"action": "delete",
"auth": "delete",
"name": "删除"
}
]
}
]
}
语法介绍
-
has_not
: 判断某个字段或属性是否存在。如果不存在,则执行创建属性。 -
expr
: 指定要扩展的位置,支持简略语法:-
columns.name
、buttons.name
、tbar.name
:通过name
属性定位。 - 示例:
tabs[?(@.name=='item_info_tab')]..columns.desc
。
-
-
position
: 指定插入位置,可选值:-
after
:插入在指定位置之后。 -
before
:插入在指定位置之前。 -
replace
:替换内容。 -
attributes
:添加属性。
-
-
body
: 扩展的内容,可以是字段、按钮、标签页等。
2. 编写 A 视图
声明菜单,view 指定视图的类型
"mom_material_menu": {
"name": "mom_material_menu",
"display_name": "物料",
"model": "Material",
"view": "material_grid,material_search,material_form",
"sequence": 2,
"active": true,
"parent_ids": {
"@ref": "mom_config_menu"
}
}
2.1 声明 A 的表单视图,这里定义了一个标签页
{
"material_form": {
"body": {
"columns": [],
"tabs": [
{
"header": "基本资料",
"rowspan": 1,
"name": "item_info_tab",
"body": {
"type": "formPart",
"model": "Material",
"columns": []
}
}
{
"header": "设计资料",
"rowspan": 1,
"name": "item_design_info_tab",
"body": {
"type": "formPart",
"model": "Material",
"columns": [
]
}
}
],
"type": "form"
},
"mode": "primary",
"model": "Material",
"name": "物料-表单",
"type": "form"
}
}
2.2 在B app声明扩展视图
{
"views": {
"aps_buyer_tab_form_ext": {
"name": "mom-item扩展-采购资料tab",
"model": "Material",
"type": "form",
"mode": "extension", # 填扩展类型
"inherit_ids": {
"@ref": "siemes.material_form" # 指定对应 siemes app 要扩展的视图
},
"body": {
"jsonpath": [
{
"expr": "tabs[?(@.name=='item_info_tab')]..columns.desc", # 扩展的位置,通过 name 找到 tab 里面的字段
"position": "before", # 扩展的位置
"body": [
"zhichengluxiam" # 扩展的内容,新增一个字段
]
},
{
"expr": "tabs[?(@.name=='item_info_tab')]..columns.shengchantiqianqi",
"position": "after",
"body": [
"gongyicanshufenlei"
]
},
{
"has_not": "tabs", # 判断是否有 tabs
"expr": "tabs[?(@.name=='item_design_info_tab')]", # 找到指定的 tab
"position": "after",
"body": [ # 扩展的内容
{
"header": "采购资料",
"body": {
"type": "formPart",
"model": "Material",
"columns": [
"caigouziliao",
"caigouyuan",
"caigoutiqianqi"
]
}
}
]
}
]
}
}
}
}
3. 示例:
- 扩展表单,给表单的一个字段后面新增一个字段
- 给表单的tab页新增一个字段
{ "views": { "test_eam_fault_maintenance_order_form_ext": { "mode": "extension", "inherit_ids": { "@ref": "newSdkApp.test_eam_fault_maintenance_order_form" }, "model": "test_eam_fault_maintenance_order", "name": "故障工单-表单", "type": "form", "body": { "jsonpath": [ { "expr": "columns.repairDate", "position": "after", "body": [ { "displayName": "报修单号2扩展", "name": "reportNo2", "groupConf": { "name": "故障信息", "id": "repairInfoGroup" } } ] }, { "expr": "tabs[?(@.name=='maintenanceInformationTab')]..columns.responseTime", "position": "after", "body": [ { "displayName": "报修单号acceptedBy扩展", "name": "reportNo2" } ] } ] } } } }
4. 常用 expr
示例
-
新增一个字段:
{ "expr": "columns.fieldName", "position": "after", "body": [ { "name": "newField", "displayName": "新字段" } ] }
-
替换一个字段:
{ "expr": "columns.fieldName", "position": "replace", "body": [ { "name": "replacedField", "displayName": "替换字段" } ] }
-
新增一个按钮:
{ "expr": "buttons.删除", "position": "after", "body": [ { "name": "newButton", "displayName": "新按钮" } ] }
-
新增一个标签页:
{ "has_not": "tabs", "expr": "tabs[?(@.name=='item_design_info_tab')]", "position": "after", "body": [ { "header": "采购资料", "body": { "type": "formPart", "model": "Material", "columns": [ "caigouziliao", "caigouyuan", "caigoutiqianqi" ] } } ] }
-
追加一个标签页里面的按钮(之前的tab已存在tbar):
{ "has_not": "tabs", "expr": "$..tabs[?(@.name == 'mbm_wms_dispatch_order_menu_tab_allocation_detail_list')]..tbar", "position": "inside", "body": [ { "name": "桶仓收货开启", "service": "siloDelivery", "auth": "siloDelivery", "action": "siloDelivery", "isLoading": true } ] }
5. JsonPath语法
JsonPath的语法相对简单,它采用开发语言友好的表达式形式,如果你了解类C语言,对JsonPath就不会感到不适应。 JsonPath语法要点:
-
$
表示文档的根元素 -
@
表示文档的当前元素 -
.node_name
或['node_name']
匹配下级节点 -
[index]
检索数组中的元素 -
[start:end:step]
支持数组切片语法 -
*
作为通配符,匹配所有成员 -
..
子递归通配符,匹配成员的所有子元素 -
(<expr>)
使用表达式 -
?(<boolean expr>)
进行数据筛选
下表将列举所有支持的语法,并对XPath进行比较:
XPath | JsonPath | 说明 |
---|---|---|
/ |
$ |
文档根元素 |
. |
@ |
当前元素 |
/ |
. 或[]
|
匹配下级元素 |
.. |
N/A |
匹配上级元素,JsonPath不支持此操作符 |
// |
.. |
递归匹配所有子元素 |
* |
* |
通配符,匹配下级元素 |
@ |
N/A |
匹配属性,JsonPath不支持此操作符 |
[] |
[] |
下标运算符,根据索引获取元素,XPath索引从1开始,JsonPath索引从0开始 |
| |
[,] |
连接操作符,将多个结果拼接成数组返回,可以使用索引或别名 |
N/A |
[start:end:step] |
数据切片操作,XPath不支持 |
[] |
?() |
过滤表达式 |
N/A |
() |
脚本表达式,使用底层脚本引擎,XPath不支持 |
() |
N/A |
分组,JsonPath不支持 |
注意:
- JsonPath的索引从0开始计数
- JsonPath中字符串使用单引号表示,例如:
$.store.book[?(@.category=='reference')]
中的'reference'
JsonPath示例
下面是相应的JsonPath的示例,代码来源于https://goessner.net/articles/JsonPath/,JSON文档如下:
{
"store": {
"book": [{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
}, {
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}, {
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}, {
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
接下来我们看一下如何对这个文档进行解析:
XPath | JsonPath | Result |
---|---|---|
/store/book/author |
$.store.book[*].author |
所有book的author节点 |
//author |
$..author |
所有author节点 |
/store/* |
$.store.* |
store下的所有节点,book数组和bicycle节点 |
/store//price |
$.store..price |
store下的所有price节点 |
//book[3] |
$..book[2] |
匹配第3个book节点 |
//book[last()] |
$..book[(@.length-1)] ,或 $..book[-1:]
|
匹配倒数第1个book节点 |
//book[position()<3] |
$..book[0,1] ,或 $..book[:2]
|
匹配前两个book节点 |
//book[isbn] |
$..book[?(@.isbn)] |
过滤含isbn字段的节点 |
//book[price<10] |
$..book[?(@.price<10)] |
过滤price<10 的节点 |
//* |
$..* |
递归匹配所有子节点 |