全栈低码设计开源框架json-script-rule与前端集成

前言

通过前面几篇插件的讲解,相信这个东西大家已经能够逐渐的上手并使用了,接下来便是最为重要的一环,即如何与前端进行集成了,正所谓学以致用,讲了这么多终于到了低码开发的最后阶段了,接下来便是畅快淋漓的使用它来简化开发了。

说明

目前与前端集成的总共有3种方式,下面分别说说它们的优缺点

  • 使用标签:优点是针对于简单的功能使用起来较为简单,易于理解,只需要在对应的input标签内加入指定的标签属性即可完成一个功能。缺点是对于复杂查询来说很难进行配置,比如多层嵌套的and和or条件,此外同样也需要写一些脚本才能使用,且不同的前端类型需要引入不同的json-script-rule.js去兼容才能使用,如json-script-rule-html.js,json-script-rule-vue.js
  • 配置属性:优点是较为灵活,相比较标签的配置它能够拥有更多的功能,且代码清晰只有一行,不会造成html代码的污染。缺点是需要了解json-script-rule.js中所提供的启动参数的属性含义,需要自己去封装ajax或axios等异步请求,此外如json-script-rule.js中未提供的属性也无法使用,无法像原始json方式那样能够完全使用json-script-rule的功能。
  • 原始json:优点是使用起来非常的灵活,只要json-script-rule框架内置插件所支持的功能属性它均完美的支持。缺点是适用于有一定开发经验的人,且比较了解json-script-rule各个插件的属性,因此对于初级水平的人来说不算很友好,此外json过长也容易造成代码的可读性变差。

每一种方式都有它的优缺点,使用标签的方式虽然简单直观但功能不全,原始json功能齐全但难度相对来说要大一些,所以这里我比较推荐的是折中的第二种方式。

js插件地址:https://gitee.com/ying1dudu/json-script-rule-jar.git

使用标签

使用标签的方式我们需要依赖jquery,接下来先以h5的页面做例子进行说明

<!DOCTYPE html>
<html lang="en">
<head>
    <title>json-script-rule</title>
    <script src="json-script-rule-html.js"></script>
</head>
<body>
    <div>
        <input type"text" jsr-g="xxx" jsr-g-c-t="eq" jsr-g-c-f="ZsTestPO.name" value="mmm">asddsa</input>
        <br>
        <input type="text" disabled jsr-e="group_name_edit" jsr-e-c-t="eq" jsr-e-c-f="id" value="edd">edf1</input>
        <input type="text" jsr-e="group_name_edit" jsr-e-s="name" value="edd">edf2</input>
        <br>
        <input type="text" jsr-d="group_name_delete" jsr-d-c-t="eq" jsr-d-c-f="id" value="kow"></input>
        <input type="text" jsr-d="group_name_delete" jsr-d-c-t="eq" jsr-d-c-f="name" value="owk"></input>
        <br>
        <button id="myb" type="button" onclick="jsr_start_body([{label:'jsr-g',name:'xxx',classes:['ZsTestUpdate','ZsTestPO'],type:"and"}])">oooooooo</button>
    </div>
    <script>
       function test_html_label(){
            //let body = jsr_build_body([{label:'jsr-g',name:'xxx',classes:['ZsTestUpdate','ZsTestPO'],type:"and"}]);
            //let body = jsr_build_body([{plugin:'add',name:'addTest',class:'ZsTestPO',datas:[]}]);
            //let body = jsr_build_body([{label:'jsr-e',name:'group_name_edit',class:'ZsTestPO'}]);
            //let body = jsr_build_body([{label:'jsr-d',name:'group_name_delete',class:'ZsTestPO'}]);
            //jsr_start_body(body);
        }
        function jsr_result(res){
            console.log(res);
        }
    </script>
</body>
</html>

标签属性如下:

  • jsr-g:表示查询的标签,值为执行后的结果对象的名字
  • jsr-g-c-t:表示查询条件的类型,如eq为精确查询,li为like模糊查询等
  • jsr-g-c-f:表示参与查询条件的字段
  • jsr-e:表示修改的标签,值为执行后的结果对象的名字,jsr-e-c-t和jsr-e-c-f同上面两个一样
  • jsr-d:表示删除的标签,值为执行后的结果对象的名字,jsr-d-c-t和jsr-d-c-f同上面两个一样

说明:在onclick中直接写jsr_start_body就可以了,或者放到script里写也是可以的,最终回调函数会将返回结果放到jsr_result方法中。上面在test_html_label方法中分别写了crud启动参数的例子,可以简单参考一下如何写启动参数

启动参数:

  • label:表示要收集并准备发送请求的标签类型
  • name:标签的名字,表示要收集哪些标签,因为是支持多个action,所以lebel和name两个属性来确定具体要收集哪些标签
  • class:增、删、改时所操作的类,也就是对哪个类所对应的表进行的操作
  • classes:查询时的启动参数,表示参与查询的都有哪些类
  • type:查询时查询条件之间的关联类型,有and和or,默认and,这里只支持全部相同的类型,即要么全是and,要么全是or

分析:为什么要写label和name属性,为什么启动参数的类型是数组而不是对象,这两个问题的出现都是因为action是可以同时发送多个的,比如先删除再插入,比如先查询后再更改或插入,而这都需要连续两个action才行,因为同一个action数组是同一个事务下的

最后再打开json-script-rule-html.js文件,看看他发送请求的例子

/*ajax request for example!!!!!!!!!!!*/

function jsr_start_body(body){
    $.ajax({
        url:"/json/script/rule",
        method:"post",
        data:JSON.stringify(body),
        dataType: "json",
        contentType:"application/json;charset=utf-8",
        success:function(res){
            jsr_result(res);
        },
        error:function(error){
            console.log(error);
            throw new Error("json script rule exception:you can also check the background of the logs!");
        }
    })
}

配置属性(推荐)

接下来还是先上一个例子

<script>
  import { jsr_build_body } from "@/api/system/json-script-rule";
  function test_js_body(){
    let body = jsr_build_body([{plugin:'get',name:'testList',classes:["ZsTestPO","ZsTestBO"],
      relations:{where:{equal:{"ZsTestPO.companyCode":['#&ZsTestBO.companyCode']}}},
      equal:{name:["asd",'www'],asd:['','sss'],ewq:undefined},like:{remark:["dsa"]},gt:{salary:"32",bonus:88},
      lt:{createDate:"2023-06-30 12:10:20"},page:{pageNum:1,pageSize:12},isGroupShow:false}]);
    //let body = jsr_build_body([{plugin:'add',name:'testAdd',class:'ZsTestPO',uuidd:["id"],datas:[{remark:'qwe',name:'dsa'}]}]);
    //let body = jsr_build_body([{plugin:'edit',name:'testUpdate',class:'ZsTestPO',type:'or',set:{name:"genggai"},equal:{id:['asddsa']}}]);
    //let body = jsr_build_body([{plugin:'delete',name:'testDelete',class:'ZsTestPO',equal:{id:['asddsa']},isDeleteAll:true}]);
  }
</script>

上面的例子分别展示了如何构建crud启动参数,通过这种方式来使用json-script-rule可以不需要考虑标签的处理(html是input标签vue引用element-ui的则是el-input,需要引用不同的js来分别处理),也就是说只需要上面的4行代码便可以灵活配置出crud的功能接口,那么它的启动参数都有哪些,我们可以先打开json-script-rule.js文件看看里面的启动参数的例子

/* the start arguments for example
const jsr_all_args = {                 
    params:{}                          //所有启动参数都支持的属性,表示业务参数,非插件模型参数,当有多个请求action时,会合并所有action里的params属性
}
const jsr_get_args = [{                //查询插件的启动参数例子
    plugin:'get'                       //插件类型,get表示查询插件
    name:'get action name',            //该属性必须要有,随便起一个返回结果的名字
    classes:['ClassA','ClassB'],       //表示查询的哪些实体类,"直接类名"(直接类名是以loactions配置为根节点,有包名则加包名,详情参见简介说明)
    isGroupShow:false,                 //是否将结果分组,多表查询时用于区分字段是哪个表下面的
    profile:{},                        //表示返回结果以主子表的层级关系展现,详情查看查询篇的属性说明
    fields:['name','id'],              //表示查询的字段,返回哪些字段,不写时默认全部,多表时会有class前缀,不为空时如果两个类字段名不冲突则不会有前缀
    relations:{                        //表示类和类之间的关系(表和表之间的关系)
        where:{                        //表示类和类之间的关系的条件,如果不写则默认后台po实体类配置的主外键关系
            equal:{"ClassA.companyCode":['#&ClassB.companyCode']}
        }
    }
    type:'or',                         //查询条件(非上面的类之间的关系条件)的关联类型,不写则默认是and
    equal:{"ClassA.companyCode":['#&ClassB.companyCode']},
    notEqual:{name:['asd','qweewq']},
    like:{name:['张三','李四'],remark:['他是隔壁老张']},            //配置方式时like里面是不需要加%百分号的
    notLike:{},                                                   //原始json方式时like里面是需要加%百分号的,可以灵活配置走不走索引
    in:{name:['张三','李四']},          //表示字段name的值满足为张三或者李四时的条件
    notIn:{},                          //与上面的相反,表示字段name的值不是张三或者李四时的条件
    gt:{salary:89,bonus:'72'},         //表示salary>89,bonus>'72',这里字符串和数字都可以,条件和条件之间看上面的type属性来确定是否为and或者or
    gteq:{salary:88,bonus:'71'},       //表示>=大于等于
    lt:{createDate:'2023-06-30 10:20:30'},    //表示<小于
    lteq:{salary:100,bonus:'100'},            //表示<=小于等于
    joins:[{                                  //外连接查询,包括左、右(3.2.5版本以后)、内连接查询,详情参考高级查询
        class:'ClassB',                       //joins是个数组,因此多个外连接的类需要写多个对象来表示
        type:"left",
        condition:{where:{equal:{"ClassB.id":["#&ClassA.b_id"]}}}
    }]
    page:{pageNum:1,pageSize:12}              //分页对象,不写则默认是pageNum:1,pageSize:10
}]
const jsr_add_args = [{                       //添加插件的启动参数例子
    plugin:'add',                             //插件类型,表示添加数据的插件
    name:'add action name',                   //该属性必须要有,随便起一个返回结果的名字
    class:'ClassA',                           //所要插入数据的实体类的"直接类名"
    uuid:['id'],                              //表示哪些字段采用uuid的方式自动生成
    calculate:["salary=-<salary>+0.5*(-10*10)","bonus=<bonus>-100"],   //表示对哪些字段进行计算处理,如salary的值为自身值+0.5*(-10*10),最终将计算的结果入库
    ternary:["remark==oiu?tiu:"],             //三元表达式,表示哪些字段需要经过三元达表达式计算,为空时则什么都不写,remark的值如果为oiu,则变成tiu,否则设置为空
    def:{remark:'字段为空时默认的备注信息'},    //表示哪些字段设有默认值
    datas:[{name:'王五',salary:'88'},{name:'赵六',salary:'10'}]         //要插入的数据数组,mysql数据库时需要每一个对象的属性个数相同,否则需要后台到application配置文件中配置edi.rule.open.replenishColumns为true
}]
const jsr_edit_args = [{                      //修改插件的启动参数例子
    plugin:'edit',                            //插件类型,表示修改数据的插件
    name:'edit action name',                  //该属性必须要有,随便起一个返回结果的名字
    class:'ClassB',                           //所要修改数据的实体类的"直接类名"
    set:{name:'修改后的值',remark:'修改后的值'},//所要修改的字段有哪些,修改后的值是什么
    type:'or',
    equal:{},
    notEqual:{},
    like:{},
    notLike:{},
    in:{},
    notIn:{},
    gt:{},
    gteq:{},
    lt:{},
    lteq:{}
}]
const jsr_delete_args = [{                    //删除插件的启动参数例子
    plugin:'delete',                          //插件类型,表示删除数据的插件
    name:'delete action name',                //该属性必须要有,随便起一个返回结果的名字
    class:'ClassB',                           //所要删除数据的实体类的"直接类名"
    isDeleteAll:false,                        //是否在没有设置删除条件的情况下删除全部数据,默认为false
    type:'or',
    equal:{},
    notEqual:{},
    like:{},
    notLike:{},
    in:{},
    notIn:{},
    gt:{},
    gteq:{},
    lt:{},
    lteq:{}
}]
*/

说明:以上的例子和启动参数的说明基本上已经概述了如何使用配置属性的方式来调用后端的低代码接口,首先是需要从json-script-rule.js文件中import一下jsr_build_body方法,其次使用jsr_build_body方法通过配置属性来构建body,最后需要通过自己写的ajax去请求后端,参数便是构建出来的body,方法是post,参数类型是json,可以看一下上面使用标签的ajax的例子,同时也参考一下简介中的例子来启动低码请求

import { requestRule} from "@/xxx......";
requestRule(body).then((response) => {
});

原始json(推荐有一定前端基础的人)

其实原始json的用法便是之前所有章节所讲的,如果你有一定的前端基础,对json-script-rule内置插件的属性规则也有一定的了解,那么建议你采用这种方式,因为这种方式更为灵活,功能也较为全面,而且不需要像上面两种方式那样需要导入json-script-rule.js这个文件,总之就是一句话,上面的两种方式其实它的最终目的都是通过一些手段来简化构建请求body的json,简化了json的上下层级关系,提供了直观的属性说明。但需要注意的是,采用手写json的方式需要注意前端组件数值的变化,尤其是在条件字段的值为空时需要明确你是不以这个字段为查询条件还是你所查询的是条件为空的值,这一点是有区别的,通过配置属性的方式会默认认为你是不以这个字段为查询条件的,因此虽然配置属性的方式简化了很多不必要的层级关系,但很多也都是封装好了的,这样就不够灵活,因此需要开发者清楚两者的区别。

最后:需要低码请求权限的请移步自定义开发篇,需要加密处理的请移步到框架配置篇(目前支持国密sm2非对称加密)


至此,整个json-script-rule便差不多写完了,作为设计它的人,我觉得它提供了一种全新的开发思路,设计思想,简化了后端的开发,并同时给前端提供了一种全栈的开发能力。如果你觉得它对你有所帮助,可以在之后的时间里慢慢的深入的了解一下它,同时也欢迎提供一些好的建议

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九天流云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值