文章目錄
NC Cloud單據開發詳細步驟
1. 元數據設計
2. 單據模板設置
- 打開【首頁】>【動態建模平臺】>【開發配置】>【應用管理】>【應用註冊】
3. 前端開發
結構如下
/main/index.js
import ReactDOM from 'react-dom'
import InterfaceParam from '../container/index'
ReactDOM.render(<InterfaceParam/>, document.getElementById('app'));
/container/index.js
import React, { Component } from 'react'
import { createPage, ajax, toast, promptBox, base } from 'nc-lightapp-front'
/**
* 全局配置
*/
const globalConfig = {
pagecode: '60023100p',
appcode: '60023100',
listTemplate: 'interface_param_list',
queryTemplate: 'interface_param_query'
}
/**
* 全局-請求URL配置
*/
const reqUrl = {
save: '/nccloud/hrpub/interfaceparam/SaveAction.do',
query: '/nccloud/hrpub/interfaceparam/QueryAction.do'
}
/**
* 全局-查詢參數
*/
var condi = {}
// props state setState({}) componentWillMount render
class InterfaceParam extends Component {
constructor(props) {
super(props)
/**
* 狀態機
*/
this.state = {
bdstatus:'edit'
}
/**
* 初始化模板及按鈕數據
*/
props.createUIDom(globalConfig, (data) => {
if (data.template) {
let meta = data.template;
props.meta.setMeta(meta || []);
}
props.button.setButtons(data && data.button ? data.button || [] : {})
})
this.updateBillStatus = this.updateBillStatus.bind(this);
this.deleteRow = this.deleteRow.bind(this)
this.onClickQuery = this.onClickQuery.bind(this)
this.save = this.save.bind(this)
this.refresh = this.refresh.bind(this)
}
componentWillMount() {
this.updateBillStatus();
this.refresh()
}
/**
* 保存
*/
save() {
let { getChangedRows,checkRequired } = this.props.editTable
let changeData = getChangedRows(globalConfig.listTemplate)
// 開啓表單驗證和開啓表格驗證
if (checkRequired(globalConfig.listTemplate, changeData)) {
ajax({
// 配置增加和修改保存操作的url
url: reqUrl.save,
data: {model:changeData},
success: (res) => {
if (res.success) {
toast({ color: "success", content: '保存成功' })
this.updateBillStatus()
this.refresh()
}
}
})
}
}
/**
* 刷新數據
*/
refresh() {
let { setTableData } = this.props.editTable
// if (condi.conditions) {
ajax({
// 配置增加和修改保存操作的url
url: reqUrl.query,
data: condi,
success: (res) => {
setTableData(globalConfig.listTemplate, { rows: res.data.interface_param_list.rows })
}
})
// }
}
/**
* 執行查詢
*/
onClickQuery() {
let { getAllSearchData } = this.props.search
condi = getAllSearchData(globalConfig.queryTemplate)
this.refresh()
}
/**
* 更新單據狀態
*/
updateBillStatus() {
let status = this.state.bdstatus
let { setStatus } = this.props.editTable
let bool = status == 'browse'
this.setState({bdstatus:bool?'edit':'browse'},()=>{
setStatus(globalConfig.listTemplate, bool?'edit':'browse')
this.props.button.setButtonsVisible({
Save: bool,
Cancel: bool,
Add: bool,
Delete: bool,
Refresh : !bool,
Edit : !bool,
Query: !bool
})
})
}
/**
* 刪除表體行
*/
deleteRow() {
let { deleteTableRowsByRowId, getCheckedRows,selectAllRows } = this.props.editTable
let rows = getCheckedRows(globalConfig.listTemplate)
if (rows && rows.length > 0) {
let modalDelRow = {
title: '警告',
color: 'warning',
content: '確定刪除?',
closeByClickBackDrop: false, //點擊遮罩不關閉提示框
//點擊確定按鈕事件
beSureBtnClick: () => {
for (let i = 0; i < rows.length; i++) {
deleteTableRowsByRowId(globalConfig.listTemplate,rows[i].data.rowid)
}
selectAllRows(globalConfig.listTemplate, false)
}
}
promptBox(modalDelRow);
} else {
toast({ color: "danger", content: '請先選中一條數據' });
}
}
/**
* 按鈕事件處理
* @param {} props
* @param {} btnCode 按鈕編碼
*/
onButtonClick(props, btnCode) {
let { addRow } = props.editTable
let { openAdvSearch } = props.search
switch (btnCode) {
case 'Query':
openAdvSearch(globalConfig.queryTemplate, true)
break
case 'Save':
this.save();
break
case 'Add':
addRow(globalConfig.listTemplate, 0, true, null)
break
case 'Delete':
this.deleteRow();
break
case 'Edit':
this.updateBillStatus();
break
case 'Cancel':
let modalDelRow = {
title: '警告',
color: 'warning',
content: '可能存在未保存的數據,是否繼續取消維護?',
closeByClickBackDrop: false, //點擊遮罩不關閉提示框
//點擊確定按鈕事件
beSureBtnClick: () => {
this.updateBillStatus();
}
}
promptBox(modalDelRow);
break
case 'Refresh':
this.refresh();
break
}
}
/**
* 渲染界面
*/
render() {
let { button, editTable, search } = this.props
let { createEditTable } = editTable
let { createButtonApp } = button
let { NCCreateSearch } = search
return (
<div>
<div>
<div style={{ display: 'display' }}>
{
NCCreateSearch(
globalConfig.queryTemplate,//模塊id
{
clickSearchBtn: () => this.onClickQuery(), // 查詢按鈕點擊事件回調,只返回公共查詢條件,不包含自定義查詢條件;如果有自定義查詢條件,需要業務組在clickPlanEve方法中接收查詢方案信息,並保存到業務組的state中,然後在 clickSearchBtn方法中自行合併公共條件和自定義條件。
searchBtnName: '查詢',
showClearBtn: true, // 是否顯示清空按鈕
showAdvSearchPlanBtn: true, // 高級面板中是否顯示保存方案按鈕
hideSearchCondition: true, // 隱藏候選條件
}
)
}
</div>
<div className="header">
<div>
<div className='ncc-hr-back'><span className="icon hrfont hr-left "></span></div>
</div>
<div className="btn-group">
{createButtonApp({
area: 'list',
onButtonClick: this.onButtonClick.bind(this),
popContainer: document.querySelector('.header-button-area')
})}
</div>
</div>
<div className="card-area">
<div className="nc-bill-table-area">
{createEditTable(globalConfig.listTemplate, {
showIndex: true,
showCheck: true
})}
</div>
</div>
</div>
</div>
)
}
}
export default createPage({})(InterfaceParam)
4. 後端開發
VO類
/***************************************************************\
* The skeleton of this class is generated by an automatic *
* code generator for NC product. It is based on Velocity. *
\***************************************************************/
package nc.vo.pub;
import nc.vo.pub.*;
/**
* <b> 在此處簡要描述此類的功能 </b>
* <p>
* 在此處添加此類的描述信息
* </p>
* 創建日期:
* @author
* @version NCPrj ??
*/
@SuppressWarnings("serial")
public class InterfaceParamVO extends SuperVO {
private java.lang.String pk_interface_param;
private java.lang.String code;
private java.lang.String name;
private java.lang.String value;
private java.lang.String type;
private java.lang.String note;
private java.lang.String pk_org;
private java.lang.String pk_group;
private java.lang.Integer dr = 0;
private nc.vo.pub.lang.UFDateTime ts;
public static final String PK_INTERFACE_PARAM = "pk_interface_param";
public static final String CODE = "code";
public static final String NAME = "name";
public static final String VALUE = "value";
public static final String TYPE = "type";
public static final String NOTE = "note";
public static final String PK_ORG = "pk_org";
public static final String PK_GROUP = "pk_group";
/**
* 屬性pk_interface_param的Getter方法.屬性名:主鍵
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getPk_interface_param () {
return pk_interface_param;
}
/**
* 屬性pk_interface_param的Setter方法.屬性名:主鍵
* 創建日期:
* @param newPk_interface_param java.lang.String
*/
public void setPk_interface_param (java.lang.String newPk_interface_param ) {
this.pk_interface_param = newPk_interface_param;
}
/**
* 屬性code的Getter方法.屬性名:參數編碼
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getCode () {
return code;
}
/**
* 屬性code的Setter方法.屬性名:參數編碼
* 創建日期:
* @param newCode java.lang.String
*/
public void setCode (java.lang.String newCode ) {
this.code = newCode;
}
/**
* 屬性name的Getter方法.屬性名:參數名稱
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getName () {
return name;
}
/**
* 屬性name的Setter方法.屬性名:參數名稱
* 創建日期:
* @param newName java.lang.String
*/
public void setName (java.lang.String newName ) {
this.name = newName;
}
/**
* 屬性value的Getter方法.屬性名:參數值
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getValue () {
return value;
}
/**
* 屬性value的Setter方法.屬性名:參數值
* 創建日期:
* @param newValue java.lang.String
*/
public void setValue (java.lang.String newValue ) {
this.value = newValue;
}
/**
* 屬性type的Getter方法.屬性名:參數類型
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getType () {
return type;
}
/**
* 屬性type的Setter方法.屬性名:參數類型
* 創建日期:
* @param newType java.lang.String
*/
public void setType (java.lang.String newType ) {
this.type = newType;
}
/**
* 屬性note的Getter方法.屬性名:參數說明
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getNote () {
return note;
}
/**
* 屬性note的Setter方法.屬性名:參數說明
* 創建日期:
* @param newNote java.lang.String
*/
public void setNote (java.lang.String newNote ) {
this.note = newNote;
}
/**
* 屬性pk_org的Getter方法.屬性名:組織
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getPk_org () {
return pk_org;
}
/**
* 屬性pk_org的Setter方法.屬性名:組織
* 創建日期:
* @param newPk_org java.lang.String
*/
public void setPk_org (java.lang.String newPk_org ) {
this.pk_org = newPk_org;
}
/**
* 屬性pk_group的Getter方法.屬性名:集團
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getPk_group () {
return pk_group;
}
/**
* 屬性pk_group的Setter方法.屬性名:集團
* 創建日期:
* @param newPk_group java.lang.String
*/
public void setPk_group (java.lang.String newPk_group ) {
this.pk_group = newPk_group;
}
/**
* 屬性dr的Getter方法.屬性名:dr
* 創建日期:
* @return java.lang.Integer
*/
public java.lang.Integer getDr () {
return dr;
}
/**
* 屬性dr的Setter方法.屬性名:dr
* 創建日期:
* @param newDr java.lang.Integer
*/
public void setDr (java.lang.Integer newDr ) {
this.dr = newDr;
}
/**
* 屬性ts的Getter方法.屬性名:ts
* 創建日期:
* @return nc.vo.pub.lang.UFDateTime
*/
public nc.vo.pub.lang.UFDateTime getTs () {
return ts;
}
/**
* 屬性ts的Setter方法.屬性名:ts
* 創建日期:
* @param newTs nc.vo.pub.lang.UFDateTime
*/
public void setTs (nc.vo.pub.lang.UFDateTime newTs ) {
this.ts = newTs;
}
/**
* <p>取得父VO主鍵字段.
* <p>
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getParentPKFieldName() {
return null;
}
/**
* <p>取得表主鍵.
* <p>
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getPKFieldName() {
return "pk_interface_param";
}
/**
* <p>返回表名稱.
* <p>
* 創建日期:
* @return java.lang.String
*/
public java.lang.String getTableName() {
return "pub_interface_param";
}
/**
* <p>返回表名稱.
* <p>
* 創建日期:
* @return java.lang.String
*/
public static java.lang.String getDefaultTableName() {
return "pub_interface_param";
}
/**
* 按照默認方式創建構造子.
*
* 創建日期:
*/
public InterfaceParamVO() {
super();
}
@nc.vo.annotation.MDEntityInfo(beanFullclassName = "nc.vo.pub.InterfaceParamVO" )
public IVOMeta getMetaData() {
return null;
}
}
業務處理接口
package nc.itf.hr.pub;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import nc.bs.dao.DAOException;
import nc.vo.pub.InterfaceParamVO;
public interface InterfaceParamService {
int save(List<InterfaceParamVO> voList) throws DAOException;
List<InterfaceParamVO> query(JSONObject jsonObj) throws DAOException;
void checkedUnique(InterfaceParamVO vo) throws Exception;
}
業務接口實現類
package nc.impl.hr.pub;
import java.util.Date;
import java.util.List;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.hr.frame.persistence.SimpleDocServiceTemplate;
import nc.itf.hr.pub.InterfaceParamService;
import nc.jdbc.framework.SQLParameter;
import nc.vo.pub.BusinessException;
import nc.vo.pub.InterfaceParamVO;
import nc.vo.pub.VOStatus;
import nc.vo.pub.lang.UFDateTime;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class InterfaceParamServiceImpl implements InterfaceParamService {
private SimpleDocServiceTemplate serviceTemplate;
private BaseDAO baseDao;
private SimpleDocServiceTemplate getServiceTemplate() {
if (serviceTemplate == null) {
serviceTemplate = new SimpleDocServiceTemplate("KpiAssign");
}
return serviceTemplate;
}
private BaseDAO getBaseDao(){
if(baseDao == null){
baseDao = new BaseDAO();
}
return baseDao;
}
@Override
public int save(List<InterfaceParamVO> voList) throws DAOException {
/**
* 更新:1 新增:2 刪除:3
*/
int exeRow = 0;
for (int i = 0; i < voList.size(); i++) {
InterfaceParamVO vo = voList.get(i);
vo.setPk_org("");
vo.setPk_group("");
vo.setTs(new UFDateTime(new Date()));
if(vo.getStatus() == VOStatus.UPDATED) {
exeRow = getBaseDao().updateVO(vo) > 0 ? exeRow++:exeRow;
} else if(vo.getStatus() == VOStatus.NEW) {
exeRow = getBaseDao().insertVO(vo)!=null ? exeRow++:exeRow;
} else if(vo.getStatus() == VOStatus.DELETED) {
vo.setDr(1);
exeRow = getBaseDao().updateVO(vo) > 0 ? exeRow++:exeRow;
}
}
return exeRow;
}
@Override
public List<InterfaceParamVO> query(JSONObject jsonObj) throws DAOException {
StringBuffer whereStr = new StringBuffer();
whereStr.append(" nvl(dr,0)=0 ");
SQLParameter param = new SQLParameter();
if(!jsonObj.isEmpty()) {
String logic = (String) jsonObj.get("logic");
JSONArray conditions = jsonObj.getJSONArray("conditions");
for(int i=0;i<conditions.size();i++) {
JSONObject condi = (JSONObject) conditions.get(i);
String field = (String) condi.get("field");
String oprtype = (String) condi.get("oprtype");
String firstvalue = (String) ((JSONObject) condi.get("value")).get("firstvalue");
if(firstvalue != null && !("").equals(firstvalue)) {
whereStr.append(" " + field + " ");
whereStr.append(oprtype + " ");
whereStr.append("? ");
param.addParam(firstvalue);
whereStr.append(logic);
}
}
}
List<InterfaceParamVO> list = (List<InterfaceParamVO>) getBaseDao().retrieveByClause(InterfaceParamVO.class, whereStr.toString(), param);
return list;
}
@Override
public void checkedUnique(InterfaceParamVO vo) throws Exception {
String code = vo.getCode();
String name = vo.getName();
InterfaceParamVO[] vos = null;
if(vo.getStatus() == VOStatus.UPDATED) {
vos = getServiceTemplate().queryByCondition(InterfaceParamVO.class, "nvl(dr,0)=0 AND code = '" + code + "' and pk_interface_param!='" + vo.getPk_interface_param() + "'");
if(vos != null && vos.length > 0) {
throw new BusinessException("編碼已存在,請重新輸入");
}
vos = getServiceTemplate().queryByCondition(InterfaceParamVO.class, "nvl(dr,0)=0 AND name = '" + name + "' and pk_interface_param!='" + vo.getPk_interface_param() + "'");
if(vos != null && vos.length > 0) {
throw new BusinessException("名稱已存在,請重新輸入");
}
} else if(vo.getStatus() == VOStatus.NEW) {
vos = getServiceTemplate().queryByCondition(InterfaceParamVO.class, "nvl(dr,0)=0 AND code = '" + code + "'");
if(vos != null && vos.length > 0) {
throw new BusinessException("編碼已存在,請重新輸入");
}
vos = getServiceTemplate().queryByCondition(InterfaceParamVO.class, "nvl(dr,0)=0 AND name = '" + name + "'");
if(vos != null && vos.length > 0) {
throw new BusinessException("名稱已存在,請重新輸入");
}
}
}
}
upm文件
<?xml version="1.0" encoding="UTF-8"?>
<module>
<public>
<component priority="0" singleton="true" remote="true" tx="CMT" supportAlias="true">
<interface>nc.itf.hr.pub.InterfaceParamService</interface>
<implementation>nc.impl.hr.pub.InterfaceParamServiceImpl</implementation>
</component>
</public>
</module>
保存action
package nccloud.web.hrpub.interfaceparam.action;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.itf.hr.pub.InterfaceParamService;
import nc.vo.pub.InterfaceParamVO;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.container.IRequest;
import nccloud.web.hr.pub.HRCommonAction;
import nccloud.web.hr.pub.ParseDataUtils;
import nccloud.web.uapbd.commons.web.ParamUtils;
public class SaveAction extends HRCommonAction {
@Override
public <T> Object execute(IRequest req, T param) throws Exception {
InterfaceParamService service = ServiceLocator.find(InterfaceParamService.class);
ParamUtils paramUtils = new ParamUtils(req);
List<Map<String, Object>> modelList = paramUtils.getList("model", null);
JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(modelList));
List<InterfaceParamVO> voList = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
InterfaceParamVO vo = new InterfaceParamVO();
String status = jsonArray.getJSONObject(i).getString("status");
JSONObject values = jsonArray.getJSONObject(i).getJSONObject("values");
vo = ParseDataUtils.parseVO(vo, values);
vo.setStatus(Integer.parseInt(status));
service.checkedUnique(vo);
voList.add(vo);
}
return service.save(voList);
}
}
查詢action
package nccloud.web.hrpub.interfaceparam.action;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import nc.itf.hr.pub.InterfaceParamService;
import nc.vo.pub.InterfaceParamVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDouble;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.ui.model.GridModel;
import nccloud.framework.web.ui.model.row.Cell;
import nccloud.framework.web.ui.model.row.Row;
import nccloud.framework.web.ui.pattern.grid.Grid;
import nccloud.web.hr.pub.HRCommonAction;
import nccloud.web.uapbd.commons.web.ParamUtils;
public class QueryAction extends HRCommonAction {
@Override
public <T> Object execute(IRequest req, T param) throws Exception {
ParamUtils paramUtils = new ParamUtils(req);
JSONObject jsonObj = JSON.parseObject(paramUtils.getRequestString());
InterfaceParamService service = ServiceLocator.find(InterfaceParamService.class);
List<InterfaceParamVO> voList = service.query(jsonObj);
List<Row> rowList = new ArrayList<>();
Grid grid = new Grid();
if(voList != null && voList.size() > 0) {
for (int i = 0; i < voList.size(); i++) {
InterfaceParamVO vo = voList.get(i);
Row row = new Row();
String[] attrs = vo.getAttributeNames();
for (int j = 0; j < attrs.length; j++) {
Cell cell = new Cell();
String attr = attrs[j];
Object obj = vo.getAttributeValue(attr);
// 處理NC類型
if(obj instanceof UFDouble) {
cell.setValue(((UFDouble)obj).doubleValue());
} else if (obj instanceof UFBoolean) {
cell.setValue(((UFBoolean)obj).booleanValue());
} else {
cell.setValue(obj);
}
row.addCell(attr, cell);
}
rowList.add(row);
}
}
GridModel model = new GridModel();
model.setAreacode("interface_param_list");
model.add(rowList);
grid.setModel(model);
return grid;
}
}
數據轉換工具類
package nccloud.web.hr.pub;
import java.lang.reflect.Field;
import nc.vo.pub.SuperVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class ParseDataUtils {
public static <T> T parseFormVO(SuperVO vo, JSONObject jsonObj) {
JSONArray formArray = jsonObj.getJSONArray("rows");
if (formArray != null && formArray.size() > 0) {
JSONObject form = ((JSONObject) formArray.get(0)).getJSONObject("values");
return parseVO(vo, form);
}
return null;
}
public static <T> T parseListVO(SuperVO vo, JSONArray jsonArray) {
if(jsonArray != null && jsonArray.size() > 0) {
SuperVO[] vos = new SuperVO[jsonArray.size()];
for (int i = 0; i < vos.length; i++) {
JSONObject jsonObj = jsonArray.getJSONObject(i).getJSONObject("values");
vos[i] = parseVO(vo, jsonObj);
}
return (T) vos;
}
return null;
}
/**
*
* @param vo
* @param jsonObj
* @return
*/
public static <T> T parseVO(SuperVO vo, JSONObject jsonObj) {
Field[] fields = vo.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
String attrName = fields[i].getName();
String attrType = fields[i].getGenericType().toString();
Object attr = null;
if (jsonObj.getJSONObject(attrName) != null) {
attr = jsonObj.getJSONObject(attrName).get("value");
}
if (attr != null && !("").equals(attr)) {
if (attrType.endsWith("String")) {
vo.setAttributeValue(attrName, (String) attr);
} else if (attrType.endsWith("Integer")) {
vo.setAttributeValue(attrName, Integer.parseInt((String) attr));
} else if (attrType.endsWith("UFDouble")) {
vo.setAttributeValue(attrName, new UFDouble((String) attr));
} else if (attrType.endsWith("UFBoolean")) {
vo.setAttributeValue(attrName, new UFBoolean((Boolean)attr));
} else if (attrType.endsWith("UFDateTime")) {
vo.setAttributeValue(attrName, new UFDateTime((String) attr));
} else if (attrType.endsWith("UFDate")) {
vo.setAttributeValue(attrName, new UFDate((String) attr));
}
}
}
return (T) vo;
}
}
請求映射配置
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<actions>
<action>
<name>hrpub.interfaceparam.SaveAction</name>
<label>保存</label>
<clazz>nccloud.web.hrpub.interfaceparam.action.SaveAction</clazz>
</action>
<action>
<name>hrpub.interfaceparam.QueryAction</name>
<label>查詢</label>
<clazz>nccloud.web.hrpub.interfaceparam.action.QueryAction</clazz>
</action>
</actions>
請求授權配置
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<authorizes>
<authorize>
<appcode>*</appcode>
<actions>
<action>hrpub.interfaceparam.SaveAction</action>
<action>hrpub.interfaceparam.QueryAction</action>
</actions>
</authorize>
</authorizes>