NCC轻量化开发数据结构总结
·目录
1、树形结构Tree
- 有些单据结构可能需要用到树形展示,后端往前端传数据的时候就需要将数据封装成树形的结构
- 每一个VO都需要通过继承nccloud.web.uapbd.commons.tree.TreeWapper这个类,可实现给前台返回树形结构的数据
- 一般需要重写getId、getCode、getName、getPid、getInnercode和getData
- getId:主键值
- getCode:显示编码
- getName:显示名称
- getPid:上级主键,没有的话一般设置成一个固定值,方便前台渲染
- getInnercode:内码,有些树是通过内码渲染的
- getData:这个方法返回一个Map,可以根据需要自定义字段和值
- 最后使用的时候就可以先调用有参的构造方法将VO传递进去,然后通过类中的getTree()方法将VO数据组装成树
返回json示例
{
"data":[
{
"iconBox":{"editIcon":true,"delIcon":true,"addIcon":true},
"key":"1001ZZ1000000000OL1C",
"title":"Demo1",
"refname":"Demo1",
"refpk":"1001ZZ1000000000OL1C",
"id":"1001ZZ1000000000OL1C",
"name":"Demo1",
"pid":"ROOT",
"innercode":"EVEI",
"code":"Demo1",
"nodeData":{
"name":"Demo1",
"innercode":"EVEI",
"ts":"2020-10-25 13:15:49"
},
"children":[]
}
],
"success":true
}
2、表单结构Form
2.1 前端Form转VO
- 通过FormOperator类中的toVO(IRequest request)方法将请求转化成VO
- 因为Form是一个表单,只能传递一个VO数据,不能传递数组
请求json示例
{
"model":{
"areaType":"form",
"rows":[
{
"values":{
"modifiedtime":{
"display":null,
"value":null
},
"modifier":{
"display":"游军文",
"value":"1001ZZ1000000000OPNV"
}
},
"status":"1"
}
]
},
"pageid":"10140AC_schemeeditor"
}
* 注:前端传过来的数据中有个status字段,这个对应VOStatus类中的状态,代表数据是新增、修改、删除还是原封不动,如果是调用的toVO方法转的VO,可以通过VO的getStatus()方法获取到
2.2 后端VO转Form
- 通过FormOperator类中的toForm(Object vo)方法将请求转化成VO
* 注:这里后端VO转Form的过程中会涉及到翻译的问题,需要在应用注册的模板设置里面将表单关联的VO类的全类名加上,不然toForm的过程会空指针。
- 后端返回给前端的数据一般包含display和value,前者一般是参照类型的字段才会有的,用于前台显示,后者用于存储真实数据。貌似还有一个精度字段,暂时没有碰到过这类数据。
返回json示例
{
"data": {
"pageid": "182001016A_card",
"card_head": {
"rows": [
{
"status": "0",
"isOptimized": false,
"values": {
"pk_group": {
"value": "0001A110000000000D5U"
},
"hasten_bef_day": {},
"enablestate": {
"display": "已启用",
"value": "2"
}
}
}
],
"areacode": "card_head"
}
},
"success": true
}
3、表格结构Grid
3.1 前端Grid转VO
- 与表单类似,通过GridOperator类的toVOs(IRequest request)方法将表单数据转化成VO的数组。和表单不同的是,这里必须用VO数组来接收,不然会报错
请求json示例
{
"pageid":"182001052A_card",
"model":{
"areaType":"table",
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"swbit":{
"value":"3"
},
"pk_balancecond":{
"value":"1001ZE10000000003HSK"
},
"status":{
"value":"0"
},
"ts":{
"value":"2020-10-25 00:49:18"
}
},
"rowid":"770400.babb32a8b54ab01",
"filter":false
},
{
"status":"2",
"values":{
"modifiedtime":{
"scale":null,
"display":"",
"value":""
},
"opr":{
"scale":null,
"display":""
},
"numberindex":{
"value":"6"
}
}
}
]
}
}
* 注:status字段的值就是前面说到的状态,代表这条数据是保存的、删除的还是其他状态的,具体可以参考VOStatus类
3.2 后端VO转Grid
- 一般列表查询的时候用的多,将需要返回的VO数组通过GridOperator类的toGrid(Object[] vos)方法转换
- 同样的,转换过程中会进行翻译,与Form表单不同的是,GridOperator类的构造需要页面编码,同时,转成Grid的时候,需要指定具体的区域编码(如果模板上只有一个表格区域,则会默认取这个表格区域,这个时候就可以不指定区域编码)。
返回json示例
{
"data":{
"pageid":"182001016A_list",
"list":{
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"pk_group":{
"display":"用友集团",
"value":"0001A110000000000D5U"
},
"hasten_bef_day":{
},
"enablestate":{
"value":"2"
}
}
},
{
"status":"0",
"isOptimized":false,
"values":{
"pk_group":{
"display":"用友集团",
"value":"0001A110000000000D5U"
},
"hasten_bef_day":{
},
"enablestate":{
"value":"2"
}
}
}
],
"allpks":[
"1001ZE10000000014OMZ",
"1001ZE10000000015Y1A"
],
"areacode":"list"
}
},
"success":true
}
* 注:这里出现了allpks,这个是给卡片页的单据翻页组件用的,还可以传递分页的信息,由于我这里数据量不大,所以没有写分页功能
3.2.1 分页处理方法
4、参照结构Ref
- 参照的话和重量端差不多,平台提供的参照有三种。分别是树形参照(继承nccloud.web.refer.DefaultTreeRefAction类)、表型参照(继承nccloud.web.refer.DefaultGridRefAction类)、树表型参照(这个是两次请求)。
- 编写参照类的话可以参考NCC技术文档,这里总结一下我开发参照的一些理解和遇到的一些问题。
4.1 参照开发
4.1.1 参照开发大致流程
- 先根据参照的类型,继承对应的类,编写相应的参照,注册好鉴权等xml后由前端开发人员编写js代码,前端人员封装好后会给一个url。
- 我们要做的就是将这个url注册到数据库表bd_refinfo对应参照的refpath字段中
- 然后在元数据的参照页签上面加上刚刚注册的参照即可
参照代码示例
4.1.2 我理解的轻量端参照
- 模板中配置好某个字段的参照类型。
- 当点击参照的时候,根据模板中配置好的参照类型去数据库表bd_refinfo中获取配置好的refpath字段值。
- 然后根据这个字段值去获取js代码,js代码中会调用后端写好的参照类,从而获取参照信息。
- 如果字段不是通过模板配置出来的字段需要参照的话,也可以通过直接调用refpath字段的url来获取参照信息。
4.1.3 开发过程遇到的问题
- 在取参照的过程中需要拼接whereSql,有时候需要拼接in语句,比如组织的参照需要获取登录有权限的组织主键,然后拼到in语句中,但是in语句里面内容不能超过1000条。这个时候第一时间想到的是创建临时表。但是,参照类是在nccloud\client组件里面的,这里和nc端不是通过你一个事务,所以临时表是不管用的。
- 解决方案;平台的RefQueryInfo类中有一个filterPks变量,将所有pk值传到这个字段里面即可,在执行参照的SQL时,平台会在nc端创建临时表处理。
refQueryInfo.setFilterPks(orgpks);
- 查询的时候,如果需要创建临时表,得启用事务,得在相应查询接口的upm文件里面加上这个,此接口才允许创建临时表,不然临时表里面会没数据
- 参照除了标准的重写的那些方法,还可以重写下面两个方法
- 上图是父类方法中构造参照结果的方法,红框中的两个方法含义如下:
processRefPks():这个是处理查询出来的pk,平台默认没有做处理,如果实际开发过程中有需要处理查询出来的pk的,可以重写该方法
processRefRows():这个是处理查询结果,平台默认是在这个方法里面做了翻译处理,如果要重写记得用super调用,或者直接将平台代码拷贝过来在里面添加东西,实际开发可能需要加根节点,或者需要对额外的字段做翻译,则需要重写该方法做处理 - 如果重写以上方法还不能解决问题的话,可以直接重写上图的 processData() 方法。不过要注意的是,参照返回的结果格式是有规范的,如果格式不正确,前端还需另做处理,浪费开发时间。后端返回数据一定要是 nccloud.framework.web.processor.refgrid.RefQueryResult 类的对象。
- 上图是父类方法中构造参照结果的方法,红框中的两个方法含义如下:
请求json示例(树形+列表形)
{
"busiParamJson":"{\"pid\":\"\",\"pageInfo\":{\"pageSize\":50,\"pageIndex\":-1},\"keyword\":\"\",\"queryCondition\":{\"pk_org\":\"0001Z41000000000L7ZM\"}}",
"sysParamJson":{
"busiaction":"我的单据-合并请求",
"appcode":"182001016A",
"tabid":"",
"ts":1603776535585,
"from":"",
"pagecs":1604653003616
}
}
返回json示例(树形)
{
"data": {
"rows": [
{
"isleaf": true,
"pid": "1001ZE10000000000KU4",
"refname": "1",
"refpk": "1001ZE10000000006H1P",
"values": {
"pk_tasksort": {
"value": "1001ZE10000000006H1P"
},
"pk_parent": {
"value": "1001ZE10000000000KU4"
},
"name": {
"value": "1"
}
}
},
{
"isleaf": false,
"refname": "111",
"refpk": "1001ZE10000000000KU4",
"values": {
"pk_tasksort": {
"value": "1001ZE10000000000KU4"
},
"pk_parent": {},
"name": {
"value": "111"
}
}
}
]
},
"success": true
}
返回json示例(列表形)
{
"data": {
"page": {
"pageIndex": "-1",
"pageSize": "50",
"total": "0",
"totalPage": "0"
},
"rows": [
{
"refcode": "344",
"refname": "本级及上级",
"refpk": "1001ZE100000000069GV",
"values": {
"pk_keygroup": {
"display": "单位,会计月",
"value": "00000000000000000011"
},
"code": {
"value": "344"
},
"name": {
"value": "本级及上级"
}
}
},
{
"refcode": "502",
"refname": "502",
"refpk": "1001ZE100000000069HW",
"values": {
"pk_keygroup": {
"display": "单位,会计月",
"value": "00000000000000000011"
},
"code": {
"value": "502"
},
"name": {
"value": "502"
}
}
}
]
},
"success": true
}
4.2 SqlBuilder
- SqlBuilder需要实现nccloud.framework.web.processor.IRefSqlBuilder接口,可重写里面的getExtraSql方法来拼接额外的SQL,跟参照开发类似。
- SqlBuilder里面的SQL是附加的SQL,一般在已有参照不满足实际的情况下使用。
- 加了这个就不需要往数据库里面注册,直接在请求的时候加上一个条件:
"TreeRefActionExt":"树形SqlBuilder全类名";
"GridRefActionExt":"列表SqlBuilder全类名";
- 平台有一个默认的SqlBuilder,叫nccloud.web.refer.sqlbuilder.DefaultRefSqlBuilder,里面做了管控模式、过滤停用数据和数据权限的SQL拼接
- 其中管控模式需要在参照的构造方法中设置元数据的id,不然不会拼接管控模式的SQL
setMdClassId(String strMdClassId);
- 过滤停启用同理,需要设置是否过滤停启用,不过使用这个得注意,得检查参照查询的表里面有没有“enablestate”字段,没有就设置为空或者不加下面代码即可,不然会报错
setShowDisabledData(Boolean blAddEnableStateWherePart);
SqlBuilder代码示例
请求json示例
{
"busiParamJson":"{\"pid\":\"\",\"pageInfo\":{\"pageSize\":50,\"pageIndex\":-1},\"keyword\":\"\",\"queryCondition\":{\"pk_org\":\"0001Z41000000000L7ZM\", \"GridRefActionExt\":\"nccloud.web.ufoe.pub.refcondition.ReportManaStruSqlBuilder\"}}",
"sysParamJson":{
"busiaction":"我的单据-合并请求",
"appcode":"182001016A",
"tabid":"",
"ts":1603776535585,
"from":"",
"pagecs":1604653003616
}
}
5、高级查询Action
- 高级查询传入的参数格式是固定的,可直接用nccloud.dto.baseapp.querytree.dataformat.QueryTreeFormatVO去接收
请求json示例
{
"busiParamJson":"{\"pageCode\": \"182001016A_list\",\"querycondition\": {\"logic\": \"and\",\"conditions\": []},\"userdefObj\": {\"pk_org\": \"GLOBLE00000000000000\",\"pk_busiprop\": \"0001Z0100000000005CQ\",\"showDisable\": true},\"oid\": \"1001ZE1000000001HEUI\",\"querytype\": \"tree\"}",
"sysParamJson":{
"busiaction":"我的单据-合并请求",
"appcode":"182001016A",
"tabid":"",
"ts":1603776535585,
"from":"",
"pagecs":1604908834284
}
}
- 如果继承了nccloud.web.action.NCCAction方法,可直接重写getParaClass(),将返回值类型改成QueryTreeFormatVO类型,这样,在接收的时候就可以直接将para强转为QueryTreeFormatVO类型
代码示例
注:不属于高级查询中的条件的额外条件,与前端开发人员商量好后放在userdefObj里面即可
- 高级查询一般返回列表数据,返回格式请参考后端VO转Grid
如何将QueryTreeFormatVO转化为查询的whereSql?
代码示例
- 先通过nccloud.framework.web.querytemplet.QueryUtil4NCC工具类将QueryTreeFormatVO转化成查询方案IQueryScheme
- 然后通过IQueryScheme的getWhereSQLOnly()方法去获取whereSql
6、主子表结构BillCard/ExtBillCard
- 主子表结构分为一主一子(BillCard)和一主多子(ExtBillCard),是标准单据比较常用的一种结构,实际上就是“Form + Grid”的结构,一主一子也可以用ExBillCard来做转化(不推荐)。这里只拿ExtBillCard来举例,BillCard的用法是一样的
6.1 前端BillCard/ExBillCard转AggVO
- 与表单和表格类似,通过BillCardOperator/ExtBillCardOperator类的toBill(IRequest request)方法将主子表数据转化成AggVO。
请求json示例
{
"pageid":"10611004_card",
"head":{
"card_head":{
"areaType":"form",
"rows":[
{
"values":{
"pk_unitsetting":{
"value":"1001Z01000000004ISDJ"
},
"pk_group":{
"display":"集成测试集团",
"value":"0001A510000000002W69"
},
"pk_org":{
"display":"北京分公司",
"value":"0001A510000000003VJ9"
}
},
"status":"1"
}
],
"areacode":"card_head"
}
},
"bodys":{
"unitBill":{
"areaType":"table",
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"pk_unitsetting_bill":{
"value":"1001Z01000000004ISDO"
},
"pk_tradetype":{
"disabled":false
},
"pk_objectregister":{
"display":"付款结算单",
"value":"0000Z3ERM000000000F5"
},
"pk_printtemplate":{
"display":"NCC付款结算卡片",
"value":"1001Z610000000007592",
"disabled":false
}
},
"rowid":"892110.062b882126ab7637",
"disabled":false
}
],
"areacode":"unitBill"
},
"unitAcc":{
"areaType":"table",
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"pk_objectregister":{
"display":"现金日记账",
"value":"0000Z0TM000000000005"
},
"archive_account":{
"value":"1001Z01000000004ISDJ"
},
"moduleid":{
"display":"现金管理",
"value":"3607"
}
},
"rowid":"892040.03a143989008a0444",
"disabled":false
}
],
"areacode":"unitAcc"
}
},
"templetid":"1001Z01000000002SGJS"
}
6.2 后端AggVO转BillCard/ExtBillCard
- 一般列表查询的时候用的多,将需要返回的AggVO数组通过BillCardOperator/ExtBillCardOperator类的toCard(Object vo)方法转换
返回json示例
{
"data":[
{
"pageid":"10611004_card",
"templetid":"1001Z01000000002SGJS",
"head":{
"card_head":{
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"pk_group":{
"display":"集成测试集团",
"value":"0001A510000000002W69"
},
"pk_org":{
"display":"北京分公司",
"value":"0001A510000000003VJ9"
}
}
}
],
"areacode":"card_head"
}
},
"bodys":{
"unitAcc":{
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"pk_objectregister":{
"display":"现金日记账",
"value":"0000Z0TM000000000005"
},
"moduleid":{
"display":"现金管理",
"value":"3607"
}
}
}
],
"areacode":"unitAcc"
},
"unitBill":{
"rows":[
{
"status":"0",
"isOptimized":false,
"values":{
"pk_objectregister":{
"display":"付款结算单",
"value":"0000Z3ERM000000000F5"
},
"archive_bill":{
"value":"1001Z01000000004ISDJ"
},
"moduleid":{
"display":"现金管理",
"value":"3607"
}
}
}
],
"areacode":"unitBill"
}
}
}
],
"success":true
}