RPA JS 扩展开发文档

RPA JS 扩展开发文档

  • SDK接口说明
  • 代码示例

›All Blog Posts

All Blog Posts

  • 使用VS Code插件在本地调试页面代码
  • 如何不使用VS Code和Chrome工具进行RPA开发
  • [Web]明细代码示例
  • [Web]CPQ产品配置页扩展
  • RPAJS中如何实现AOP开发
  • [H5]商机,报价,订单明细自定义编辑页面
  • [H5]自定义实体,表单子实体批量示例
  • [H5]表单页代码示例
  • [H5]详情页代码示例
  • [H5]系统级API示例
  • [H5]调试RPA JS扩展代码
  • [H5]在自定义页面中使用RPA SDK
  • [Mobile]调试RPA JS扩展代码
  • [Web][新版]表单页代码示例
  • [Web]明细表格API示例
  • [Web]系统级API示例
  • [Web]表单页代码示例
  • [Web]列表页代码示例
  • [Web]详情页代码示例
  • [Web]调试RPA JS扩展代码
  • RPA JS 更新日志
  • RPA JS 常见问题Q&A
  • RPA JS 扩展开发介绍

使用VS Code插件在本地调试页面代码

March 15, 2021

使用VS Code插件,我们可以在本地直接调试开发中的页面。
在本地启用静态资源服务器,通过内网ip地址访问页面,保存后刷新就能看到修改后的页面,而不用“禁用,打包,上传,启用”后才能看到修改后的效果。

  1. 打开VS Code插件,登录

  2. 点击“打开页面布局项目”按钮,选择一个空的文件夹作为项目根目录

  3. 项目中的第一层文件夹与Admin的页面代码一一对应,点击刷新按钮可以重新拉取服务器端的所有页面代码,其中:

  • 文件夹图标表示尚未上传页面代码
  • 红点的文件夹图标表示已经上传了页面代码,但没有启用
  • 绿点的文件夹图标表示上传并启用了页面代码
  1. 右键点击下载并解压按钮同步线上的页面代码,或者新建一个静态页面

  2. 点击“开启/关闭本地开发服务器”按钮,启动本地静态资源服务器

  3. 开发服务器启动成功后,可以看到服务器的ip地址和端口号

  4. 在浏览器中可以打开所有的静态资源

  5. 在Admin中新建自定义菜单,跳转的地址填入本地服务器页面地址,注意:
    网页端https访问http有跨域问题,需要使用localhost;移动端要保证手机和电脑在同一个局域网内,使用ip地址访问

  6. 在网页端/移动端设计器中选择上一步中的自定义菜单,保存。在浏览器或者手机中查看效果

如何不使用VS Code和Chrome工具进行RPA开发

January 18, 2021

当实施环境不能使用VS Code和Chrome工具时,可以在浏览器Console中使用RPA API进行保存和发布。注意这种方法并不能完全替代VS Code和Chrome工具,应仅用于特殊情况下的RPA JS扩展代码保存和发布。

打开浏览器控制台

浏览器按F12,进入开发者调试界面。

示例:Chrome的console界面,在红色框内输入代码进行操作:

Chrome的console界面

获取全部RPA扩展点

rpa.api.getExtInstances()

得到的结果:

{
  "account.ListPage#*#ListPage": {
    "description": "客户列表页",
    "id": "account.ListPage#*#ListPage",
    "extType": "EntityListPageExtensionPoint",
    "type": "UI"
  },
  "account.ListPage#*#setHighSea.Button": {
    "description": "初始化公海池分组 批量按钮",
    "id": "account.ListPage#*#setHighSea.Button",
    "extType": "ButtonExtensionPoint",
    "type": "UI"
  },
  "SystemUtils": {
    "description": "SystemUtils",
    "extType": "SystemUtils",
    "id": "SystemUtils",
    "type": "Code"
  },
  ...
}

根据数据新建扩展点

格式:const name = new xsyrpa.${extType}("${id}")

示例:

const abc = new xsyrpa.ButtonExtensionPoint("account.ListPage#*#setHighSea.Button")

保存RPA代码

⚠️注意:保存RPA代码功能不会发布,不影响用户正在使用的RPA扩展代码

// 要保存的代码必须为一个function
var code = function(){
  ...
}
// 保存当前打开的客户端
// 如果当前打开的是web端,则保存tenant.rpa.extensions.web
// 如果当前打开的是h5企微端,则保存tenant.rpa.extensions.h5
rpa.api.saveCode(code)

// 保存到 web = 网页端,h5 = 企微端,mobile = app端
rpa.api.saveCode(code, "web")
rpa.api.saveCode(code, "h5")
rpa.api.saveCode(code, "mobile")

发布RPA代码

⚠️注意:发布RPA代码会更新用户正在使用的RPA 扩展代码

⚠️注意:通过console发布的RPA代码,如果使用了ES6语法,则无法支持IE。如果需要支持IE,请仅使用ES5语法。

// 要发布的代码必须为一个function, 不能用箭头函数等ES6语法
var code = function(){
  ...
}
// 发布当前打开的客户端
// 如果当前打开的是web端,则发布tenant.rpa.extensions.web
// 如果当前打开的是h5企微端,则发布tenant.rpa.extensions.h5
rpa.api.deployCode(code)

// 发布到指定客户端,web = 网页端,h5 = 企微端,mobile = app端
rpa.api.deployCode(code, "web")
rpa.api.deployCode(code, "h5")
rpa.api.deployCode(code, "mobile")

[Web]明细代码示例

January 5, 2021

1.1 报价单,订单自定义产品Picker

Event: pickerClick Method: afterPickerSelected

//系统方法实例
const ext_SystemUtils = new xsyrpa.SystemUtils();
//明细扩展实例
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
//监听明细picker点击+号
ext_quote_CPQPriceSetsExtensionPoint.on('pickerClick', (data, resolve, reject) => {
    //接收到的系统明细picker打开需要的参数
    console.log(data);
    ext_SystemUtils.openDialog({
        url: 'customPickerUrl',
        windowSize:2,
        title: "自定义选择产品"
    }).then(function(data){
        //data 为产品ids
        //调用系统添加明细数据方法
        ext_quote_CPQPriceSetsExtensionPoint.afterPickerSelected({ids: data});
    });
});

1.2 报价单、订单明细字段值的设置和清空

Method: setDetailData

//明细扩展实例
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
// 获取当前所有明细数据
ext_quote_CPQPriceSetsExtensionPoint.getDetailData().then((data) => {
    // data  as array
    console.log(data);
    // 方法1:单个字段修改
    
    // 设置第一条明细的数量字段为10
    ext_quote_CPQPriceSetsExtensionPoint.setDetailData({
        detailId: data[0].id,    // 指定明细数据的id
        detailUuid: data[0].detailUuid,  // 指定明细的uuid
        apiKey: 'quantity',      // 指定明细的字段apikey
        value: 10       // 指定明细指定字段的值
    });
    // 清空值设置value为空(清空报价单明细销售单价)
    ext_quote_CPQPriceSetsExtensionPoint.setDetailData({
        detailId: data[0].id,    // 指定明细数据的id
        detailUuid: data[0].detailUuid,  // 指定明细的uuid
        apiKey: 'price',      // 指定明细的字段apikey
        value: ''       // 指定明细指定字段的值
    });
    
    // 方法2 设置第二条数据的多个字段值 (仅支持CPQ)
    data[1].quantity = 10;
    data[1].detailRemarks = 'edit by RPA';
    ext_quote_CPQPriceSetsExtensionPoint.setDetailData({
        data: data
    });
    
    ext_quote_CPQPriceSetsExtensionPoint.refreshDetail(); //刷新显示
});

1.3 报价单、订单明细字段设置必填 、 只读、 可见属性

Method:

setColumnRequired 设置列必填 setCellRequired 设置单元格必填

setColumnEditable 设置列只读/可编辑 setCellEditable 设置单元格必填/可编辑

setColumnVisible 设置列可见 setCellVisible 设置单元格可见

//明细扩展实例
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
// 方法1: 设置整列必填
/*
  设置列可见/只读/必填
  需要在beforeLoad监听中调用才生效
  可按明细业务类型设置,可同时设置多个字段
  传参如下:
   config: [
      {entityType:'', itemApiKey: 'xxx', visible(editable|required): true/false }    // 全部明细业务类型下的指定字段可见/只读
      {entityType:'xxxx', itemApiKey: 'xxx', visible(editable|required): true/false } // 指定明细业务类型下的指定字段可见/只读
   ]
*/

// 设置所有明细业务类型的备注字段必填
ext_quote_CPQPriceSetsExtensionPoint.on('beforeLoad', (data,resolve)=>
{
    ext_quote_CPQPriceSetsExtensionPoint.setColumnRequired({
        config:[{
            entityType:'',
            itemApiKey: 'detailRemarks',
            required: true
        }]
    });
    resolve();
})

// 方法2  设置某条明细某个字段必填
// 设置新添加的第一条明细数据的备注字段必填

// 添加新的明细数据后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterAddDetail', () => {
   // 获取当前所有明细数据
    ext_quote_CPQPriceSetsExtensionPoint.getDetailData().then((data) => {
        ext_quote_CPQPriceSetsExtensionPoint.setCellRequired({
            detailId: data[0].id,   
            detailUuid: data[0].detailUuid,  
            itemApiKey: 'detailRemarks',     
            required: true
        });
    });
});

1.4 报价单、订单明细行操作按钮设置可见性

Method: setDetailButtonVisible

//明细扩展实例
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
//设置第一行的删除按钮隐藏
ext_quote_CPQPriceSetsExtensionPoint.getDetailData().then((data) => {
    ext_quote_CPQPriceSetsExtensionPoint.setDetailButtonVisible({
        detailId: data[0].id,   
        detailUuid: data[0].detailUuid,  
        buttonType: 'delete',  //copy | priceBook(仅CPQ) | bundle (仅CPQ) 
        visible: false
    });
});

1.5 报价单、订单明细删除后事件

Event:afterDelDetail

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");

ext_quote_CPQPriceSetsExtensionPoint.on('afterDelDetail', (data) => {console.log(data)});

1.6 报价单、订单明细删除行,增加行

Method:

delDetailData hideDetail clearDetailData afterPickerSelected

// 删除明细的数据
ext_quote_CPQPriceSetsExtensionPoint.delDetailData({
     detailId,   // 指定明细的id
     detailUuid, // 指定明细的uuid
     hide        // true/false, 明细删除后是否隐藏(针对编辑时已保存的明细, 系统默认已保存过的明细删除时,显示带删除线)
});

// 设置行数据隐藏
ext_quote_CPQPriceSetsExtensionPoint.hideDetail({
      detailUuid,
      detailId,
      visible  // true/false
});
 
// 清空行数据(删除)
ext_quote_CPQPriceSetsExtensionPoint.clearDetailData();

// 增加行
// 由于订单,报价单明细是需要有映射转换的,因此可以直接使用 afterPickerSelect 方法来添加行。传递产品id即可。
    //data 为产品ids
    //调用系统添加明细数据方法
    ext_quote_CPQPriceSetsExtensionPoint.afterPickerSelected({ids: data});
    

2.1 商机、自定义实体(旧表单)明细自定义Picker

//商机明细自定义picker
//创建商机明细扩展实例
const ext_opportunityProduct_Form_opportunityProduct = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.Form#*#opportunityProduct-919228631532061");
//系统方法实例
const ext_SystemUtils = new xsyrpa.SystemUtils();
// 监听商机明细picker点击+号
ext_opportunityProduct_Form_opportunityProduct.on('pickerClick', function(data){
    //接收到的系统商机明细picker打开需要的参数
    console.log(data);
    //打开Dialog, 链接到自定义页面
    //自定义页面调用Api等方式(可将data传入作为参数)获取产品信息,这里随便使用一个该租户的产品为例
    ext_SystemUtils.openDialog({
        url: 'https://www.reynanote.com/?id=963469313770032',
        windowSize:2,
        title: "自定义选择产品"
    }).then(function(data){
        //data 为产品ids
        //调用系统添加明细数据方法
        ext_opportunityProduct_Form_opportunityProduct.afterPickerSelected({ids: data});
    });
});
 
/*
    自定义页面
*/
//自定义页面 传值 关闭picker
//自定义按钮,点击时
function(){
    let msg = {
      isvData: 1,2,3 //选择的数据ids,
      doClose: true
    };
    window.top.postMessage(msg, '*');
}

2.2 商机、自定义实体(旧表单)明细字段值的设置和清空

//商机明细某业务类型明细表格实例
const oppDetail = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_6822980");
//设置第一行数据的数量为20
oppDetail.setCellValue({
    rowIndex: 1,
    itemApiKey: 'amount',
    value: 20
});
//清空第一行的单价
oppDetail.setCellValue({
    rowIndex: 1,
    itemApiKey: 'priceUnit',
    value: ''
});

2.3 商机、自定义实体(旧表单)明细字段的只读,可见,必填属性

Method: setCellVisible //设置单元格可见 setCellReadonly //设置单元格只读 setCellEditable // 设置单元格可编辑 setCellRequired //设置单元格必填

const oppDetail = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_6822980");
//设置第一行单价不可见
oppDetail.setCellVisible({
    rowIndex: 1,
    itemApiKey: 'priceUnit',
    visible: false
});

//设置第一行数量只读
oppDetail.setCellReadonly({
    rowIndex: 1,
    itemApiKey: 'amount',
    readonly: true
});

//设置第一行数据的价格表价格可编辑
oppDetail.setCellEditable({
    rowIndex: 1,
    itemApiKey: 'standardPrice',
    editable: true
});

//设置第一行数据的折扣必填
oppDetail.setCellRequired({
    rowIndex: 1,
    itemApiKey: 'discount',
    required: true
});

2.4 商机、自定义实体(旧表单)明细行操作按钮设置可见性

Method: setOperateButtonVisible

const oppDetail = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_6822980");
// 隐藏第一行数据的删除按钮
oppDetail.setOperateButtonVisible({
     buttonType: "delete", //"edit" | "delete" | "copy"
     visible: false,
     rowIndex: 1,
     //id  //编辑时可以传数据id来定位行
})


2.5 商机、自定义实体(旧表单)明细行删除后事件

Event: deleteRowData

const oppDetail = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_6822980");

oppDetail.on("deleteRowData", (data) => {console.log(data)})

2.6 商机、自定义实体(旧表单)明细删除行、增加行

Method: deleteDetail clearDetails

const oppDetail = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_6822980");

//删除第一行数据
oppDetail.deleteDetail({
    rowIndex: 1,
    //  id: //传递id时,之后保存会真实删除。
})

// 清空明细 (仅支持新建时)
oppDetail.clearDetails();

// 增加行
// 商机明细需要产品映射等逻辑,因此可以直接使用afterPickerSelect来添加行
//创建商机明细扩展实例
const ext_opportunityProduct_Form_opportunityProduct = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.Form#*#opportunityProduct-919228631532061");
//data 为产品ids
//调用系统添加明细数据方法
ext_opportunityProduct_Form_opportunityProduct.afterPickerSelected({ids: data});

//自定义明细,有批量依据时可以尝试使用afterPickerSelect来添加新行。
//没有批量依据的明细暂不支持添加行

//实例化订单编辑明细页扩展点
const ext_order_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("order_CPQPriceSetsExtensionPoint");
//监听保存前事件
ext_order_CPQPriceSetsExtensionPoint.on('beforeSave', async function(data, resolve, reject){
    //获取当前明细数据
    const detailData = await ext_order_CPQPriceSetsExtensionPoint.getDetailData();
    console.log(detailData);
    let pass = true;
    //遍历数据
    for(let i=0; i< detailData.length ; i++){
        const currentDetail = detailData[i];
        //当数据中的产品名称为1234时
        if(currentDetail['productId-label'] == "1234"){
            pass = false;  //设置不能保存
            //设置明细上的错误提示
            ext_order_CPQPriceSetsExtensionPoint.setDetailError({
                detailUuid: currentDetail.detailUuid,
                errorMsg: '不能选择产品1234'
            });
        }
    }
    if(pass){
        resolve();  //继续保存
    }else {
        reject();    //阻止保存
    }
});

[Web]CPQ产品配置页扩展

January 5, 2021

1.1 设置产品选项配置页字段样式

仅支持字段颜色

//明细扩展实例
const ext_order_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("order_CPQPriceSetsExtensionPoint");
//监听产品配置页渲染前事件
ext_order_CPQPriceSetsExtensionPoint.on('beforeOptionLoaded', (data, resolve)=>{
    ext_order_CPQPriceSetsExtensionPoint.setColumnStyle({
    itemApiKey: '', //字段ApiKey
    fontColor: '#c3daf9' //色值或 red, blue等
    });
    resolve(); //继续渲染
});

1.2 产品选项配置页自定义筛选条件

//明细扩展实例
const ext_order_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("order_CPQPriceSetsExtensionPoint");

//设置筛选条件
ext_order_CPQPriceSetsExtensionPoint.setOptionsFilterCondition({
    itemApiKey: '', //字段apiKey
    value: '' //模糊匹配值
});

1.3 产品选项配置页自定义校验规则,设置错误提示

//明细扩展实例
const ext_order_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("order_CPQPriceSetsExtensionPoint");
//监听产品配置页点击配置价格按钮,产品选项转明细前事件
ext_order_CPQPriceSetsExtensionPoint.on('beforeConvertToDetails', (data,resolve,reject)=>{
    console.log(data);  //data {checkedData} 是当前所选产品和产品选项数据
    ext_order_CPQPriceSetsExtensionPoint.setOptionsError({
        errors:[{
            detailUuid:"", //选项的detailUuid , 从data中获取
            msg:'' //错误信息提示
        }]
    });
    reject(); //阻止继续转换明细
});

1.4 产品选项配置页勾选/取消勾选时事件

//明细扩展实例
const ext_order_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("order_CPQPriceSetsExtensionPoint");
//监听产品配置页点击配置价格按钮,产品选项转明细前事件
ext_order_CPQPriceSetsExtensionPoint.on('optionChecked', (data)=>{
    console.log(data);  //data {checkedData} 是当前所选产品和产品选项数据
});

RPAJS中如何实现AOP开发

December 21, 2020

RPAJS中如何实现AOP开发

适用范围

Web端、移动端、H5端

现状、问题

RPAJS主要用于前端扩展开发,属于面向扩展点开发的一种模式。因此每个扩展点实例都拥有一个唯一的ID作为标识。应用在表单的不同布局实例上,也就需要用到不一样的ID来应对不同布局可能需要不同扩展逻辑的需求。免得具体实例写扩展逻辑比较静态,同样也带来了通用逻辑需要书写多次的问题

AOP开发思路

为了解决通用逻辑代码重复的问题,SDK提供了面向扩展点类型的切面。每个扩展点都是一个实例,每个实例都会有对应的扩展类型。AOP示意图:

  1. 每个表单的扩展实例,就会对应一个类型FormExtensionPoint
  1. 每个类型都对应一个AOP类,FormExtensionPoint对应的就是FormExtensionPointBatch

    公式: AOP类型名称 = 扩展点类型名称+Batch

  1. 每个切面类型还可以通过ID的通配符进行细分,例如
new FormExtensionPointBatch("Account.*")

通配符基本符号

  • ? 可以匹配任何单个字符
  • *** ** 可以匹配任意字符串(包括空字符串)

应用实例

针对Account实体的所有业务类型和布局使用AOP


//定义一个表单的AOP类

const contactForm = 
new xsyrpa.FormExtensionPointBatch(["xsy.breeze.web.contact.*.masterEntityCreation.*#*#"]) 
//AOP类型只用于监听多个来源,所以监听函数中多一个参数extInfo
contactForm.on("loaded",(data,resolve,reject,extInfo)=>{
//监听到的该类型具体扩展Id
const extId = extInfo.extId
//使用该extId可以创建不同的其他相关扩展实例,比如表单字段
//根据规则来,表单项ID=表单ID+字段APIKey
const formItemDepart = new xsyrpa.FormTextInputExtensionPoint(extId+"depart");

formItemDepart.setValue("demo");

});

一些原则

AOP类型只能用于监听多个扩展实例的事件,也就是批量监听是允许的。

AOP类型不能用于批量发送数据(设值操作等),因为在picker列表新建数据场景中同一个业务类型和布局的表单允许同时打开多个

[H5]商机,报价,订单明细自定义编辑页面

December 3, 2020

Author: 王晓峰

页面进入后的初始化,数据组装前事件:beforeLoad

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
ext_quote_CPQPriceSetsExtensionPoint.on(
  "beforeLoad",
  (data, resolve, reject) => {
    //可以拿到当前页面的明细数据
    const details = data.details;
    console.log("rpa-beforeLoad");
  }
);

页面进入后的初始化,第一屏数据显示前事件:afterInitDetail

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
ext_quote_CPQPriceSetsExtensionPoint.on(
  "afterInitDetail",
  (data, resolve, reject) => {
    //可以拿到当前页面的明细数据
    const details = data.details;
    console.log("rpa-afterInitDetail");
  }
);

添加产品后的回填:AfterAddDetail

跳转到价格配置页面后,通过右下角的添加按钮添加产品返回后会触发此事件

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
ext_quote_CPQPriceSetsExtensionPoint.on(
  "AfterAddDetail",
  (data, resolve, reject) => {
    console.log("rpa-AfterAddDetail");
  }
);

编辑明细进入后的事件:AfterEditDetail

进入到价格配置页面,数据加载完成后触发此事件

返回的 data 参数中会包含 fromType 字段,表示来源于哪个场景,目前支持的场景
复制(商机,报价,订单): 2
生成(商机生成报价,报价生成订单): 3
编辑(报价,订单): 4
商机编辑明细(商机编辑单独的): 5

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
ext_quote_CPQPriceSetsExtensionPoint.on(
  "AfterEditDetail",
  (data, resolve, reject) => {
    let fromType = data.fromType;
    //判断如果是生成场景,就执行清除明细的action
    if (fromType == "3") {
      ext_quote_CPQPriceSetsExtensionPoint.addCustomAction({
        action: "deleteAllDetails",
      });
    }
    console.log("rpa-AfterEditDetail");
  }
);

编辑明细进入后的事件:AfterDeleteDetail

从详情页点击编辑跳转到价格配置页面后会触发此事件

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
//删除明细后的监听事件
ext_quote_CPQPriceSetsExtensionPoint.on(
  "AfterDeleteDetail",
  (data, resolve, reject) => {
    //返回删除的明细数据
    //data格式:[{index:0,detail:{明细}},{index:1,detail:{明细}}]
    console.log("rpa-AfterDeleteDetail" + JSON.stringify(data));
  }
);

保存前的事件:beforeSave

价格配置页面底部保存按钮点击事件

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
//保存前的监听事件
ext_quote_CPQPriceSetsExtensionPoint.on(
  "beforeSave",
  (data, resolve, reject) => {
    console.log("rpa-beforeSave");
    //继续走保存的话执行resolve()
    resolve();
  }
);

明细被修改后的事件:rowDataChange

价格配置页面底部保存按钮点击事件

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
//单条明细被修改后的监听事件
ext_quote_CPQPriceSetsExtensionPoint.on(
  "rowDataChange",
  (data, resolve, reject) => {
    //data:被修改的明细数据
    //结构:{ price:100,price_changed:true }
    //解析:修改的apikey会对应的多一个子端apiKey_changed字段,用来表示某个字段的值被修改了
    console.log("rpa-rowDataChange====" + JSON.stringify(data));
    resolve();
  }
);

价格配置页面点击添加产品按钮的自定义 picker 事件:pickerClick

价格配置页面内,通过右下角的添加按钮添加产品时可以跳转自定义 picker 页面

价格配置页面添加产品方法:afterPickerSelected

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
ext_quote_CPQPriceSetsExtensionPoint.on(
  "pickerClick",
  (data, resolve, reject) => {
    //接收到的系统明细picker打开需要的参数
    console.log(data);
    //ids中放置需要添加的产品id
    //afterPickerSelected:添加产品回到价格配置页面
    //ids数组:放置产品id的列表
    //id:产品的id
    ext_quote_CPQPriceSetsExtensionPoint.afterPickerSelected({
      ids: [1487115250417700, 1487137361199105],
    });
  }
);

价格配置页面获取当前页面所有的明细:getDetailData

价格配置页面内,可以通过此方法获取当前页面的所有明细,然后进行改值操作

更新明细上的字段值: setDetailData
删除某条明细: delDetailData

const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
ext_quote_CPQPriceSetsExtensionPoint.getDetailData().then((data) => {
  console.log(data);
  //根据id|detailUuid|index更新明细上的某个字段的值
  //上述三个有一个起作用就行
  ext_quote_CPQPriceSetsExtensionPoint.setDetailData({
    index: 0,
    detailId: data[0].id, // 指定明细数据的id
    detailUuid: data[0].detailUuid, // 指定明细的uuid
    apiKey: "price", // 指定明细的字段apikey
    value: "1000", // 指定明细指定字段的值
  });
  //删除某条明细
  //可以使用id,detailUuid跟index都可以删除
  ext_quote_CPQPriceSetsExtensionPoint.delDetailData({
    index: 0,
    detailId: data[0].id, // 指定明细数据的id
    detailUuid: data[0].detailUuid, // 指定明细的uuid
  });
});

价格配置页面明细添加自定义按钮:showCustomBtnForDetail

价格配置页面内,给指定明细添加自定义按钮

//在明细上添加自定义按钮
//event:是按钮触发的事件(必须是rpa已经支持的事件,
//label:是按钮的名称,可以配置多个按钮,
//多余一个展示成更多选项,点击打开下拉选项)
//例:点击自定义按钮打开自定义picker事件:event填写自定义picker的事件名称,点击替换明细触发自定义picker
ext_quote_CPQPriceSetsExtensionPoint.showCustomBtnForDetail({
  //按钮列表
  btnList: [
    {
      event: "pickerClick",
      label: "替换明细",
    },
  ],
  //指定明细上只要有的情况下,三个标识都能使用
  // index: 1,
  detailUuid: "a21346a1-f397-4b8d-9071-bee137e18872",
  // detailId:'1468239432236693'
});

价格配置页面更换明细的产品(角标不变):setDetailDataTotal

价格配置页面内,给明细更换产品

//自定义按钮触发自定义 picker 后会导致自定义 picker 的来源有多个(还有点加号也会触发,因此在返回的参数中做区分)
ext_quote_CPQPriceSetsExtensionPoint.on(
  "pickerClick",
  (data, resolve, reject) => {
    //接收到的系统明细 picker 打开需要的参数
    console.log(data);
    //自定义 pickerClick 返回的 data 中会有一个 type 字段区分是加号过来的跟明细上更换产品点击过来的
    //"add"是加号过来的
    //"update" 是替换明细产品过来的
    if (data.type == "add") {
      ext_quote_CPQPriceSetsExtensionPoint.afterPickerSelected({
        ids: [1506744389976100],
      });
    } else if (data.type == "update") {
      //替换明细的参数
      //id:产品名称
      //index:需要更换的明细 index
      ext_quote_CPQPriceSetsExtensionPoint.setDetailDataTotal({
        id: 1506744389976093,
        index: 0,
      });
    }
  }
);

价格配置页面明细支持自定义事件:addCustomAction

价格配置页面内,给明细添加自定义事件,支持的 action

deleteAllDetails :删除所有明细
disableQuickOperater : 禁用明细上的快捷编辑按钮 openPicker : 打开产品 picker

//参数形式:
//action:要执行的事件
//extra:需要的额外参数
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint(
  "quote_CPQPriceSetsExtensionPoint"
);
//例:打开产品picker
ext_quote_CPQPriceSetsExtensionPoint.addCustomAction({
  action: "openPicker",
});
//例:删除所有明细
ext_quote_CPQPriceSetsExtensionPoint.addCustomAction({
  action: "deleteAllDetails",
});
//例:禁用编辑按钮
ext_quote_CPQPriceSetsExtensionPoint.addCustomAction({
  action: "disableQuickOperater",
  extra: {
    //是否显示编辑按钮
    //true显示
    //false不显示
    isShowQuickOperate: false,
  },
});
//例:禁用添加产品按钮
ext_quote_CPQPriceSetsExtensionPoint.addCustomAction({
  action: "disableAddProducts",
  extra: {
    //是否显示添加产品按钮
    //true 显示
    //false不显示
    isShowAddProducts: false,
  },
});
//例:禁用更多,批量操作按钮
ext_quote_CPQPriceSetsExtensionPoint.addCustomAction({
  action: "disableShowManageBtn",
  extra: {
    //是否显示更多。批量操作按钮
    //true 显示
    //false不显示
    isShowManageBtn: fasle,
  },
});

[H5]自定义实体,表单子实体批量示例

October 30, 2020

Author: 彭茜、傅腾

子实体批量依据选择器

主子明细的子实体中,需要配置"子对象支持批量新建",才能在表单中出现子实体批量依据选择器。

该扩展点可以把批量依据选择器替换成自定义逻辑。

const picker = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.masterEntityCreation.defaultPageLayout.ChildEntityPicker");
picker.on('pickerClick', (data, resolve, reject) => {
  //一定要resolve或reject
  //resolve()后,用本方法代替出厂的实体批量依据选择器
  //reject()后,弹出实体批量依据选择器
  resolve([
      {id: 1390357211070082} //将数据传到子实体列表页,必须是关联关系实体中存在的id
  ])
})

子实体列表扩展点

子实体列表 - 删除一条数据

const childEntityList = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.customEntity12__c.childEntityListCreation.defaultPageLayout.SimpleFormList");
childEntityList.deleteDetail({rowIndex: 0});

子实体列表 - 监听删除事件

const childEntityList = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.customEntity12__c.childEntityListCreation.defaultPageLayout.SimpleFormList");
childEntityList.on('deleteRowData', (data) => {
    console.log(data)
})

子实体列表 - 隐藏按钮

const childEntityList = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.customEntity12__c.childEntityListCreation.defaultPageLayout.SimpleFormList");
childEntityList.setOperateButtonVisible({
     buttonType: "delete", //目前支持删除(delete)和编辑(edit)
     visible: false,
     rowIndex: 0, //不传rowIndex隐藏全部
})

子实体列表 - 设置字段属性

//子实体列表页(生命周期)
const listPage = new xsyrpa.FormExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.customEntity12__c.childEntityListCreation.defaultPageLayout#*#");
//子实体列表
const entityList = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.customEntity12__c.childEntityListCreation.defaultPageLayout.SimpleFormList");
listPage.on("loaded", () => {
    //列表与表单不同,是一个循环处理的过程
    //列表中同一套业务逻辑、同一套UI组件,根据每一条不同的数据,显示出不同的界面
    //我们通过表达式的方式,来动态改变列表上一条记录的UI界面
    //当满足表达式时,将"customItem1__c"字段设置成只读
    entityList.setCellReadonlyRule([{itemApiKey: 'customItem1__c', rule: '$data.name === "readonly"'}]);
    //当满足表达式时,隐藏"customItem1__c"字段
    entityList.setCellInvisibleRule([{itemApiKey: 'customItem1__c', rule: '$data.name === "invisible"'}]);

    //把第"1"行的"customItem1__c"字段的值设置成"123"
    entityList.setCellValue({
        itemApiKey: "customItem1__c",
        value: "123",
        rowIndex: 1,
    });

    //监听值的变化
    entityList.on("rowDataChanged", (data)=>{
      console.log(data)
    });;
})

子实体列表 - 获取所有数据(包括明细)

//注意是list上dataModel扩展点,非list扩展点
const listDataModel = new xsyrpa.BreezeDataModelExtensionPoint("xsy.breeze.app.customEntity366__c.defaultBusiType.customEntity367__c.childEntityListCreation.defaultPageLayout_DataModel");
//子实体的apiKey
const childApiKey = 'customEntity367__c';
//子实体列表数据所在的路径
const itemsPath = `subnode.${childApiKey}.defaultBusiType.records.items`
const getItems = (dataModel) => {
    const pathArr = itemsPath.split('.');
    return pathArr.reduce((dm, path) => {
        return dm[path];
    }, dataModel);
}

//获取所有dataModel的数据
listDataModel.getValue().then((data) => {
    //找到需要的子实体列表数据
    console.log(getItems(data))
})

子实体列表 - 添加明细后的事件

const list = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.app.customEntity366__c.defaultBusiType.customEntity367__c.childEntityListCreation.defaultPageLayout.SimpleFormList");
list.on('afterAddDetail', (data) => {
  //单个添加和批量添加,会进此处回调,删除不会,请使用deleteRowData
  debugger
})

[H5]表单页代码示例

October 29, 2020

Author: 王松松、傅腾

//表单扩展点
const form = new xsyrpa.FormExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.masterEntityCreation.defaultPageLayout#*#");

//表单加载完成
form.on("loaded", (data) => {
    //表单字段扩展点
    const formItem = new xsyrpa.FormTextInputExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.masterEntityCreation.defaultPageLayout#*#customItem1__c");

    //设置值
    formItem.setValue("My Value");
    
    //获取值
    formItem.getValue().then((val) => {
        console.log(val);
    })

    //设置只读
    formItem.setReadOnly(true);
    
    //设置必填,只读字段不会显示必填的"*"号
    formItem.setRequired(true);

    //设置可见
    formItem.setVisible(true);
    
    //设置字段错误提醒,只是前端的显示,保存时不会校验
    formItem.setError("My Error");

    //设置表单的placeholder
    formItem.setPlaceholder("My Placeholder");

    //设置样式
    formItem.setInlineStyle({
      //selector是css选择器
      //了解css选择器: https://developer.mozilla.org/zh-CN/docs/Glossary/CSS_Selector
      selector: ".am-list-item",
      style: { "background": "red" },
    });

    //字段数据发生变化时,调用回调方法
    formItem.on("onChange", (data) => {
        console.log(data);
        debugger;
    });

    //关联关系替换picker事件
    const formRelatedField = new xsyrpa.FormRelatedFieldExtensionPoint("xsy.breeze.app.account.defaultBusiType.masterEntityCreation.defaultCreateLayout#*#parentAccountId");
    formRelatedField.on("pickerHookTrigger", (data, resolve, reject) => {
        resolve({
            accountName: "相关列表新建",
            id: 1387683565960837
        });
    })

});

//表单保存前触发事件
form.on("beforeSave", (data, resolve, reject) => {
    //继续保存流程
    resolve();

    //取消保存,返回表单编辑页
    //reject();
});

//表单子实体数据更新触发事件
form.on("refreshed", (data)=>{
   //data包括主实体数据和子实体整体数据
   const {master, subnode} = data;

   //根据数据更新主实体字段的值
   const formItem = new xsyrpa.FormTextInputExtensionPoint("xsy.breeze.app.customEntity11__c.defaultBusiType.masterEntityCreation.defaultPageLayout#*#customItem1__c"");
   formItem.setValue(`${subnode.customEntity11__c.defaultBusiType.records.items.length}`);
   resolve();
})

[H5]详情页代码示例

October 28, 2020

Author: 张皓帆、傅腾

隐藏按钮

// 按钮组,
// 112代表第二页,第二个tabview的第三个tab下的快捷操作菜单
//(第一个的index是0)
let shortcutgroup112 = new xsyrpa.ButtonGroupExtensionPoint("....shortcut#*#buttonGroup1_1_2");
// 快捷操作的删除按钮
let shortcutdelete = new xsyrpa.ButtonExtensionPoint("....shortcut#*#deleteCustomize");

// 快捷操作按钮组加载完毕后
shortcutgroup112.on('detailButtonGroupLoaded', () => {
    // 隐藏删除按钮
    shortcutdelete.setVisible(false)
})

重命名按钮

shortcutgroup112.on('detailButtonGroupLoaded', () => {
    // 重命名删除按钮
    shortcutdelete.setText('删!')
})

添加/删除一个自定义按钮

例子:在详情页 第二页上,从上到下第二个tabview的 第三个tab下 的快捷操作菜单 里 添加一个自定义啊按钮。点击按钮时,删除该按钮。

// 按钮组,
// 112代表第二页,第二个tabview的第三个tab下的快捷操作菜单
//(第一个的index是0)
let btngroup112 = new xsyrpa.ButtonGroupExtensionPoint("....shortcut#*#buttonGroup1_1_2");

// 快捷操作按钮组加载完毕后
btngroup112.on('detailButtonGroupLoaded', () => {

    // 添加一个按钮,id: abc,文本: halo
    btngroup112.addButton({extId: "abc", text:"halo"}).then(btn => {

        // 这里promise返回的btn即为新建的按钮
        // 点击按钮时

        btn.on('onClick', () => {
            console.log('clicked')
            
            // 根据extId删除按钮
            btngroup112.removeButton('abc')
        })
    })
})

注意,removeButton只能删除rpa添加的自定义按钮。

[H5]系统级API示例

October 27, 2020

Author: 张皓帆、傅腾

网络请求

const xRequest = new xsyrpa.XRequest();

//发起open api请求
xRequest.request({
  url: '/rest/data/v2.0/xobjects/account/description',
  headers: {},
  method: "GET"
}).then((data) => {
  //请求成功
  console.log(data)
}).catch((ex)=>{
  //请求失败
  console.log(ex)
});

//POST请求
xRequest.request({
  url: '/rest/data/v2.0/xobjects/account',
  headers: {
    'Content-Type': 'application/json'
  },
  method: 'POST',
  payload: {
    "data": {
      "accountName": "我的客户",
      "entityType": 6263664,
      "highSeaId": 366125,
      "dimDepart": 601512
    }
  }
})

//公网请求, 完整url,从"https://"开始
xRequest.request({
  url: "https://cat-fact.herokuapp.com/facts",
  headers: {},
  method: "GET"
});

通知方法

const notificationMessage = new xsyrpa.NotificationMessage();
notificationMessage.success({message: "成功"});
notificationMessage.warning({message: "警告"});
notificationMessage.error({message: "失败"});

触发确认弹框

const notificationMessage = new xsyrpa.NotificationMessage();

//触发确认框
notificationMessage.confirm({
    message: "确认保存?"
}).then(() => { 
    console.log("成功");
}).catch(() => {
    console.log("失败");
});

打开新页面

const systemUtils = new xsyrpa.SystemUtils();

//打开内部(lapp)页面,或者打开需要认证的外部网站,需要使用自定义菜单
//统一认证中心认证通过后,跳转到自定义页面,会自动在query里贴上access token
//这里返回的是开发页面中使用 (js sdk 的) systemUtils.sendBackResult() 发送的数据
systemUtils.openWindow({url: 'mcode'}).then((dataFromWindow) => {
  console.log(dataFromWindow);
});

//直接打开外部页面
systemUtils.openWindow({url: 'https://www.xiaoshouyi.com'});

例子中的'mcode'是菜单编码,在后台"开发者平台"、"自定义菜单"中配置。

打开Dialog

当要打开一个开发页面,然后让开发页面传回数据时,建议使用 openDialog()。需要注意的是,在 openDialog()打开的页面里调用sendBackResult()会关闭该 Dialog。

//'windowSize'和'title'在H5端无效果
ext_SystemUtils.openDialog({ url: "dialogCode", windowSize: 1, title: "" }).then(data => {
  ...
})

获取当前登录的用户信息

请注意,H5端用户信息是从企业微信传递过来的,需要通过企业微信手机或者桌面端App打开,才能拿到用户信息。 使用浏览器访问/bff/breeze/wxwork拿不到用户信息。

const systemUtils = new xsyrpa.SystemUtils();
systemUtils.currentUser().then((user) => {
    console.log(user);
});

返回到上一页

一般在lapp自定义页面中使用,返回到主App。

const systemUtils = new xsyrpa.SystemUtils();
systemUtils.goBack();

刷新当前页面

const systemUtils = new xsyrpa.SystemUtils();
systemUtils.refreshCurrentPage();
Next →
Copyright © 2021 销售易