前言:本文建立在有过用友开发经验以及已有BIP前端对应模块源码,前后端开发环境均已搭建好的基础上进行自定义参照二开。
表型参照开发总体步骤
一、数据库维护参照数据
注意:这一步是为了可以在单据模板上选择到该参照。数据库维护过之后需要重启环境,不然模板选不到该参照。
bd_refinfo 表里插入一条数据,内容可以参考已有数据
refclass 字段代表原NC参照,若只加YonBIP高级版参照此处可以为空。
refpath 字段代表 参照的前端 JS 路径,前端创建目录要和这个一致,不然会找不到参照。
mobilerefpath 字段代表移动端参照的前端 JS 路径,没有移动端则可以忽略
注意需要抽取参照脚本。
以自定义工单参照请购单为例:
INSERT INTO BD_REFINFO (CODE, DR, ISTREELAZYLOAD, ISNEEDPARA, ISSPECIALREF, LAYER, METADATANAMESPACE, METADATATYPENAME, MOBILEREFPATH, MODULENAME, NAME, PARA1, PARA2, PARA3, PK_COUNTRY, PK_INDUSTRY, PK_REFINFO, REFCLASS, REFPATH, REFSYSTEM, REFTYPE, RESERV1, RESERV2, RESERV3, RESID, RESIDPATH, TS, WHEREPART, WORKFLOWCONDITIONUSEUNITORG) VALUES('sscwo_praybill', 0, 'Y', NULL, NULL, NULL, 'sscwo', 'praybill', NULL, 'sscwo', '参照请购单拆单', NULL, NULL, NULL, NULL, NULL, '0001Z610001CDMCC9999', '', 'sscwo/public/refer/praybillgridref/index', NULL, 0, NULL, NULL, NULL, '参照请购单拆单', 'ref', '2024-10-24 11:06:02', NULL, NULL);
二、鉴权文件维护
以自定义工单为例:
Authorize鉴权文件路径:{biphome}\hotwebs\nccloud\WEB-INF\extend\yyconfig\modules\sscwo\freebill\config\authorize\authorize.xml
在Authorize.xml文件中找到下面这部分配置(如果没有把这段直接复制到鉴权文件也可以,要放在<authorizes></authorizes>这对标签里面)。
<authorize>
<appcode>*</appcode>
<actions></actions>
</authorize>
在<actions></actions>标签内新增自己的鉴权配置,如下配置。
<authorize>
<appcode>*</appcode>
<actions>
<!-- 参照请购单 -->
<action>sscwo.freebill.PrayBillGridRef</action>
</actions>
</authorize>
Action映射文件路径:{biphome}\hotwebs\nccloud\WEB-INF\extend\yyconfig\modules\pu\poorder\config\action\freebill.xml
在freebill.xml文件中新增如下配置
<!-- 参照请购单 -->
<action>
<name>sscwo.freebill.PrayBillGridRef</name>
<label>参照请购单</label>
<!-- 后台类全路径 -->
<clazz>nccloud.web.sscwo.freebill.action.refer.PrayBillGridRefAction</clazz>
</action>
Authorize 鉴权文件<action></action>
标签内的配置需要和Action 映射文件<name></name>
标签内的配置保持一致,否则会找不到后台类导致参照失效。
三、前端开发
在前端工程 sscwo/public/refer/praybillgridref/下编写index.js,复制将下列代码,更改为自己请求
import React from 'react';
import { high } from 'nc-lightapp-front';
const { Refer } = high;
export default function(props = {}){
var conf = {
multiLang: {
moduleId: '7020',//应用注册应用编码
domainName: 'sscwo',//模块名
currentLocale: 'simpchn'//固定写法
},
refName: '参照请购单拆单',//参照弹出窗名
refCode: "nccloud.web.sscwo.action.refer.PrayBillGridRefAction",//对应后端类全路径
queryGridUrl: "/nccloud/sscwo/freebill/PrayBillGridRef.do",//固定写法为queryGridUrl:"/nccloud/xx/xx/xx.do",其中xx/xx/xx.do对应鉴权文件<action></action>标签内的配置
isMultiSelectedEnabled: false,//是否开启多选,不配置默认为false。
columnConfig: [{
name: ['请购单号','组织'],
code: ["refcode",'refname']
}],//参照展示字段
refType: "grid"//参照类型,这里为grid-表型,还有tree-树型和gridTree-左树右表型
};
return <Refer {...conf} {...props} />
}
四、后端开发
package nccloud.web.sscwo.freebill.action.refer;
import nccloud.framework.web.processor.refgrid.RefQueryInfo;
import nccloud.framework.web.ui.meta.RefMeta;
import nccloud.pubitf.platform.db.SqlParameterCollection;
import nccloud.web.refer.DefaultGridRefAction;
public class PrayBillGridRefAction extends DefaultGridRefAction {
public PrayBillGridRefAction(){
super();
}
@Override
public RefMeta getRefMeta(RefQueryInfo arg0) {
// TODO Auto-generated method stub
RefMeta refMeta = new RefMeta();
refMeta.setCodeField("vbillcode");//code 参照编码
refMeta.setNameField("name");//name 参照名称
refMeta.setPkField("pk_praybill");//pk主键 参照主键
refMeta.setTableName(getRefTable());//参照表名 查询的表,一般是实体vo中默认对应的表,部分情况需要自己写子查询拼表
refMeta.setExtraFields(new String[]{"vbillcode","name"});//需要查询的额外字段
refMeta.setMutilLangNameRef(true);//多语
return refMeta;
}
private String getRefTable() {
StringBuffer sb = new StringBuffer();
sb.append("( ");
sb.append(" SELECT DISTINCT h.vbillcode vbillcode,o.name name,h.pk_praybill pk_praybill");
sb.append(" FROM po_praybill h ");
sb.append(" INNER JOIN po_praybill_b b ON h.pk_praybill = b.pk_praybill ");
sb.append(" LEFT JOIN org_orgs o ON h.pk_org = o.PK_ORG ");
sb.append(" WHERE b.vbdef20 !='Y' AND NVL(b.dr,0)=0 AND NVL(h.dr,0)=0 and h.fbillstatus = 3");
sb.append(" AND h.pk_praybill NOT IN(SELECT def15 FROM lfw_zdydj WHERE def15 IS NOT NULL AND NVL(dr,0)=0 AND transtype = 'zdydj-Cxx-24' ) ");
sb.append(" )");
return sb.toString();
}
@Override
public String getExtraSql(RefQueryInfo refQueryInfo, RefMeta refMeta) {
// TODO Auto-generated method stub
return super.getExtraSql(refQueryInfo,refMeta);
}
@Override
public SqlParameterCollection getExtraSqlParameter(RefQueryInfo refQueryInfo, RefMeta refMeta) {
// TODO Auto-generated method stub
String pk_group = getPk_group(refQueryInfo);
SqlParameterCollection collParam = new SqlParameterCollection();
collParam.addChar(pk_group);
return collParam;
}
/**
* 设置order by语句。不重写该方法会默认按refmeta中的codeField排序
*/
@Override
public String getOrderSql(RefQueryInfo refQueryInfo, RefMeta refMeta) {
// TODO Auto-generated method stub
return "ORDER BY vbillcode desc";
// return super.getOrderSql(refQueryInfo, refMeta);
}
}
常见问题:
1.单据模板选择新增的参照之后打开单据字段显示空,没有选择框。
解决办法:将前端代码,后端代码都打到home里面,在重启环境即可正常显示。
2.点击参照框报错找不到类
解决办法:
先清除浏览器缓存或者使用浏览器无痕模式在选择试试,如果依旧报错则需要从数据库维护数据开始排查。
数据库维护的refpath 这个字段值对应前端js类路径,需要保持一致
Authorize鉴权文件中<action></action>
标签内的配置需要和Action 映射文件<name></name>
标签内的配置保持一致,否则会找不到后台类导致参照失效。
Action 映射文件<clazz></clazz>
标签内配置需要和后台类保持一致。
检查前端index.js文件中
refCode: "nccloud.web.sscwo.action.refer.PrayBillGridRefAction",//对应后端类全路径
queryGridUrl: "/nccloud/sscwo/freebill/PrayBillGridRef.do",//固定写法为queryGridUrl:"/nccloud/xx/xx/xx.do",其中xx/xx/xx.do对应鉴权文件<action></action>标签内的配置
refCode和queryGridUrl配置是否有误
3.选择参照保存后参照字段值为空问题,保存、提交、收回、刷新、审批均会出现此问题,可以做统一处理
解决办法:改问题出现的原因是参照字段保存后,系统标准保存方法翻译字段时,没有翻译自定义项,返回值自定义项参照字段缺少display字段值。找到保存按钮对应的后台类,再返回之前对这个字段做个处理,加上display值则可以正常显示了。
package nccloud.web.sscwo.freebill.action;
import java.util.Map;
import org.json.JSONObject;
import nc.bs.logging.Logger;
import nc.itf.pu.ws.ItfDaoTools;
import nc.itf.sscwo.comm.IQueryParyBillService;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.core.json.IJson;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.convert.translate.Translator;
import nccloud.framework.web.json.JsonFactory;
import nccloud.framework.web.ui.model.row.Cell;
import nccloud.framework.web.ui.model.row.Row;
import nccloud.framework.web.ui.pattern.billcard.BillCard;
import nccloud.framework.web.ui.pattern.billcard.BillCardOperator;
import nccloud.pubitf.sscwo.freebill.IFreeBillMainService;
import nccloud.sscwo.freebill.consts.FreeBillRequestParam;
import nccloud.sscwo.freebill.utils.FreeBillCommUtil;
import nccloud.sscwo.freebill.utils.ThreadLocalUtil;
import nccloud.web.sscwo.freebill.vo.FreeBillMetaDataBaseAggVO;
import uap.lfw.dbl.vo.MetaDataBaseAggVO;
import uap.lfw.dbl.vo.MetaDataBaseVO;
public class FreeBillSaveBillAction implements ICommonAction {
public Object doAction(IRequest request) {
IJson json = JsonFactory.create();
String read = request.read();
Map view = (Map) json.fromJson(read, Map.class);
FreeBillRequestParam param = FreeBillRequestParam.convertViewToParam(view);
String tradetype = FreeBillCommUtil.killNull(param.getParameter("tradetype"));
String uistatus = FreeBillCommUtil.killNull(param.getParameter("uistate"));
ThreadLocalUtil.setValue("current_tradetype", tradetype);
Translator translator = new Translator();
BillCard retcard = null;
try {
BillCard billcard = (BillCard) json.fromJson(read, BillCard.class);
String userjson = billcard.getUserjson();
JSONObject object = new JSONObject();
object = new JSONObject(userjson);
String pagecode = object.getString("pagecode");
BillCardOperator oper = new BillCardOperator(pagecode);
FreeBillMetaDataBaseAggVO freeBillVO = (FreeBillMetaDataBaseAggVO) oper.toBill(request);
String pk_freeform = freeBillVO.getParentVO().getPrimaryKey();
IFreeBillMainService service = (IFreeBillMainService) ServiceLocator.find(IFreeBillMainService.class);
MetaDataBaseAggVO reqAggVO = freeBillVO.toBaseAggVO();
MetaDataBaseVO head = (MetaDataBaseVO) reqAggVO.getParentVO();
if (("add".equals(uistatus)) && (StringUtils.isNotEmpty(pk_freeform))) {
head.setAttributeValue("pk_freeform", pk_freeform);
}
head.setStatus(("add".equals(uistatus)) ? 2 : 1);
head.setTranstype(tradetype);
MetaDataBaseAggVO retAggVO = service.saveBill(reqAggVO);
freeBillVO.mergeAggVO(retAggVO);
retcard = oper.toCard(freeBillVO);
oper.handleCardValidateFormula();
retcard.setPageid(pagecode);
translator.translate(retcard);
//def15增加display
IQueryParyBillService query = (IQueryParyBillService) ServiceLocator.find(IQueryParyBillService.class);
Row[] rows = retcard.getHead().getModel().getRows();
Row[] brows = retcard.getBody().getModel().getRows();
Map<String,Cell> map = rows[0].getValues();
Cell cell = null;
String vbillcode = null;
if(null != map.get("def15")) {
cell = map.get("def15");
vbillcode = query.queryDef15doc(cell.getValue(),tradetype);
cell.setDisplay(vbillcode);
}
//def15增加display end
return retcard;
} catch (Exception e) {
Logger.error(e.getMessage());
ExceptionUtils.wrapException(e);
} finally {
ThreadLocalUtil.reset();
}
return null;
}
public String getSql(Object value) {
return "select billno from lfw_zdydj where pk_freeform='"+value+"'";
}
}