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 扩展开发介绍

[H5]调试RPA JS扩展代码

October 26, 2020

Author: 傅腾

在Chrome插件中调试RPA JS扩展代码

  1. 使用浏览器打开企业微信App,https://crm.xiaoshouyi.com/bff/breeze/wxwork,其他环境请调整url,需要开通企业微信。 其余步骤与调试Web端RPA JS扩展代码相同。
  2. 拉取扩展点,编写JS扩展代码
  3. 点击"预览"按钮,把编写的JS扩展代码注入到运行时
  4. 点击"Sources"页签,在"BRZRPAWORKER"下,选择一个以uuid为名字的文件
  5. 在这个文件中可以看到刚才编写的JS扩展代码,在需要调试的行上加断点

[H5]在自定义页面中使用RPA SDK

October 25, 2020

Author: 张皓帆、傅腾

使用RPA JS扩展开发,我们可以在RPA中打开自定义页面并传递参数给这个页面。在自定义页面中处理相关的业务逻辑,并把结果返回给主app。

在自定义页面中,通过引入RPA SDK,可以调用所有的PRA的方法。下面我们分步看如何在自定义页面中使用RPA SDK。

  1. 在主App中编写并发布RPA JS扩展代码,将如下的扩展代码放入某个生命周期方法中:
const systemUtils = new xsyrpa.SystemUtils();
systemUtils.openWindow({
  url: 'hello', //菜单编码
}).then((dataFromWindow) => {
  console.log(dataFromWindow); //输出: open api请求结果
  //自定义页面如果没有主动调用sendBackResult方法,会在页面关闭时,进入此处回调方法
});
  1. 编写自定义页面,打包并上传到admin、开发者平台、页面代码之中。
<html>

<!-- 引入sdk.js,请替换成当前环境的rs地址 -->
<head><script src='https://rs.ingageapp.com/breeze/static/xsy-breeze-ui-rpa/latest/sdk.js'></script></head>

<body>
    <button onclick="handleClick()">Hello</button>
    <script>
    //和主App中编写的RPA不同,不会打包,不要使用ES6语法,兼容IE
    var systemUtils, xRequest;

    //页面和sdk加载完成后,再使用sdk的方法
    document.addEventListener('DOMContentLoaded', function() {
      systemUtils = new xsyrpa.SystemUtils();
      xRequest = new xsyrpa.XRequest();

      //如果自定义页面没有调用sendBackResult方法,会在页面关闭时,进入openWindow方法的回调
      //没有需要返回的内容,可以主动调用一次sendBackResult返回空
      //systemUtils.sendBackResult(null)
    });

    function handleClick() {
      //从query string中得到从主App中传递的参数
      var data = location.search;
      console.log(data); //输出: ...&data=some_data ,其中包括了access token

      //可以在自定义页面中调用RPA方法
      xRequest.request({
        url: `/rest/data/v2.0/xobjects/account/description`,
        headers: {},
        method: "GET"
      }).then(function(data){
        
        //将open api请求结果回传给主App
        systemUtils.sendBackResult(function(){
          //返回上一页
          systemUtils.goBack()
        })

      }).catch(function(ex){});
    }
    </script>
</body>

</html>

  1. 配置自定义菜单,类型为内部,终端为移动端,URL配置成上一步自定义页面中的地址。

  1. 通过网页端或企业微信端打开应用,验证结果。

[Mobile]调试RPA JS扩展代码

September 1, 2020

Author: 傅腾

在VS Code插件中调试移动端RPA JS扩展代码

  1. 打开VS Code插件,登入,启动WS Server,手机通过扫码连接VS Code

  2. 点击VS Code菜单中的View/Output,打开控制台

  1. 在控制台Output中选择"Breeze Extension DevTool"

  1. 拉取扩展点,编写JS扩展代码,保存,使用console.log()打印日志,点击调试按钮。

⚠️注意:移动端只能打印字符串String,传递其他类型无法打出日志。

  1. 在控制台Output右侧的下拉栏中查看log信息

[Web][新版]表单页代码示例

July 14, 2020

Author: 许强

新版表单自定义实体主子明细,子表单合计行

Quote Sub Entity

//在金额(amount)产生变化时,计算并更新总价
const subEntityTable = new xsyrpa.FormSubEntityTableExtensionPoint("xsy.breeze.web.quote.quoteLine.defaultBusiType.childEntityCreation.ec");

subEntityTable.on("onChange", (data) => {
    console.log(data);
    const sum = data.reduce((pre, curr) => {
        return (curr.amount || 0) + pre;
    }, 0);
    subEntityTable.setFooterText({
        text: "销售金额总价(元): " + sum 
    });
});

//注意:javascript有精度问题,最好将计算结果精确到几位小数
//sum.toFixed(2)

[Web]明细表格API示例

July 6, 2020

Author: 郑颍丽、江炜

订单/报价单 全屏交互 编辑明细页面

扩展点对应位置 编辑时,同样的扩展点,显示为”编辑报价单“。 (非CPQ, CPQ 订单和报价单相同,以下以报价单为例)

image2020-6-17_14-37-13

订单报价单明细API说明

//实例化扩展点
const ext_quote_CPQPriceSetsExtensionPoint =
   new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
 
/******************************************  Events  **********************************************************/
 
/*Events / outports*/
 
//编辑明细页面加载前事件
ext_quote_CPQPriceSetsExtensionPoint.on('beforeLoad', (data) => {
    //传出data为
    /*{
         parentObjectId: 父实体id,
         childObjectId: 子实体id,
         parentRecordId: 报价单数据id,
         productFamilyId: 价格表id,
         supportCalculate: 是否支持系统默认计算,
         enabledRules: 是否开通CPQ Rule License,
         isCopy: 是否是生成或复制,
         isCpq: 是否开通CPQ License,
         srcObjectId: 生成或复制来源实体id,
         srcDataId: 生成或复制来源数据id,
         parentData: 主实体数据信息
         availablePriceBookInfo: 可用的价格表信息
    }*/
});
 
//编辑明细页面加载完成后事件
ext_quote_CPQPriceSetsExtensionPoint.on('loaded', (data) => {
    //data 同beforeLoead
})
 
//编辑或生成,复制时, 首次加载明细数据后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterInitDetail', () => {
   //仅暴露事件,无数据传出
});
 
//添加新的明细数据后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterAddDetail', () => {
   //仅暴露事件,无数据传出
});
 
//编辑明细字段后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterEditDetail', (data) => {
   //data
   /*
      {
        detailId: 修改的明细数据id,
        detailUuid: 修改的明细数据uuid,
        itemApiKey: 修改的明细字段itemApiKey,
        oldValue: 字段原始值oldValue,
        newValue: 字段修改后的值newValue
      }
   */
});
 
 
//保存明细前事件
ext_quote_CPQPriceSetsExtensionPoint.on('beforeSave', (data, resolve, reject) => {
    //无data传出,如需校验,请调用getDetailData方法获取全部明细
    resolve(); //resolve()后继续执行系统保存
               //如 调用 reject() 则不执行系统保存
               // 不调用 resolve 或 reject 程序将会被挂起等待
});
 
 
//快捷保存明细前事件
ext_quote_CPQPriceSetsExtensionPoint.on('beforeQuickSave', (data, resolve, reject) => {
    //无data传出,如需校验,请调用getDetailData方法获取全部明细
    resolve(); //resolve()后继续执行系统保存
               //如 调用 reject() 则不执行系统保存
               // 不调用 resolve 或 reject 程序将会被挂起等待
});
 
/******************************************  Methods **********************************************************/
 
/*Methods / inports*/
 
// 获取当前所有明细数据
ext_quote_CPQPriceSetsExtensionPoint.getDetailData().then((data) => {
    // data  as array
});
 
// 获取指定uuid明细数据
ext_quote_CPQPriceSetsExtensionPoint.getDetailData({detailUuid: xxx}).then((data) => {
    // data  as object
});
 
// 设置明细的数据值
ext_quote_CPQPriceSetsExtensionPoint.setDetailData({
      data,    // data是所有明细数据, 批量全覆盖, 不传则set 单条明细的某个字段的值。
      detailId,    // 指定明细数据的id
      detailUuid,  // 指定明细的uuid
      apiKey,      // 指定明细的字段apikey
      value        // 指定明细指定字段的值
});
 
// 删除明细的数据
ext_quote_CPQPriceSetsExtensionPoint.delDetailData({
     detailId,   // 指定明细的id
     detailUuid, // 指定明细的uuid
     hide        // true/false, 明细删除后是否隐藏(针对编辑时已保存的明细, 系统默认已保存过的明细删除时,显示带删除线)
});
 
// 刷新明细的数据
ext_quote_CPQPriceSetsExtensionPoint.refreshDetail();
 
// 开启/禁用系统计算
ext_quote_CPQPriceSetsExtensionPoint.disableDefaultCalc({
      enabled // true/false
});
 
// 执行单条明细计算
ext_quote_CPQPriceSetsExtensionPoint.detailCalculate({
      detailUuid,
      detailId,
      itemApiKey,  //设置参与系统计算的字段的值,并触发系统计算
      newValue
});
   
// 获取价格表Id
ext_quote_CPQPriceSetsExtensionPoint.getProductFamilyId(); //获取的是一个promise对象

   
// 设置价格表Id
ext_quote_CPQPriceSetsExtensionPoint.setProductFamilyId({
    id
});
 
 
// 设置明细错误信息
ext_quote_CPQPriceSetsExtensionPoint.setDetailError({
      detailUuid,
      detailId,
      errorMsg  //错误信息文案
});
 
// 设置单元格样式 (暂不支持!!!!)
ext_quote_CPQPriceSetsExtensionPoint.setCellStyle({
      detailUuid,
      detailId,
      itemApiKey,
      fontColor?, // 字体颜色
      backgroundColor?, // 背景颜色
      borderColor? // 边框颜色
});
 
 
// 设置单元格是否可编辑
ext_quote_CPQPriceSetsExtensionPoint.setCellEditable({
      detailUuid,
      detailId,
      itemApiKey,
      editable  // true/false
});
 
// 设置单元格是否可见
ext_quote_CPQPriceSetsExtensionPoint.setCellVisible({
      detailUuid,
      detailId,
      itemApiKey,
      visible  // true/false
});
 
// 设置行数据隐藏
ext_quote_CPQPriceSetsExtensionPoint.hideDetail({
      detailUuid,
      detailId,
      visible  // true/false
});
 
// 清空行数据(删除)
ext_quote_CPQPriceSetsExtensionPoint.clearDetailData();
 
 
/*
  设置列可见/只读
  需要在beforeLoad监听中调用才生效
  可按明细业务类型设置,可同时设置多个字段
  传参如下:
   config: [
      {entityType:'', itemApiKey: 'xxx', visible(editable): true/false }    // 全部明细业务类型下的指定字段可见/只读
      {entityType:'xxxx', itemApiKey: 'xxx', visible(editable): true/false } // 指定明细业务类型下的指定字段可见/只读
   ]
*/
 
// 设置列可见
ext_quote_CPQPriceSetsExtensionPoint.setColumnVisible({
    config: any[]
});
 
// 设置列只读
ext_quote_CPQPriceSetsExtensionPoint.setColumnEditable({
    config: any[]
});

**报价单明细代码示例:从销售机会新建报价单时,商机上的明细全部删除并隐藏不显示 **

//创建报价单明细扩展实例
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
let quoteFromOpp; //是否是从商机生成报价单
let hasCleared;   //是否已经清空初始明细

//监听报价单明细配置页加载前事件
ext_quote_CPQPriceSetsExtensionPoint.on('beforeLoad', (data, resolve, reject) => {
    hasCleared = false;
    //根据data信息判断是否是商机生成明细
    if(data.isCopy && data.srcObjectId == 3){
        quoteFromOpp = true;
    }else{
        quoteFromOpp = false;
    }
    resolve(); //继续渲染
});
//监听初始明细渲染后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterInitDetail', ()=> {
    if(quoteFromOpp && !hasCleared){
        //如果是商机生成明细 并且 没有清空过明细时
        ext_quote_CPQPriceSetsExtensionPoint.clearDetailData(); //清空明细(删除并隐藏)
        hasCleared = true;
    }
});

弹窗新建编辑实体带明细(商机)

新增的明细字段控制API

  • 新建商机时 默认展开明细部分,从opportunity.subForm上 获取扩展点
const ext_opportunity_SubForm_opportunityProduct =
     new xsyrpa.FormSubEntityTableExtensionPoint("opportunity.SubForm#*#opportunityProduct");
 
ext_opportunity_SubForm_opportunityProduct.on('loaded', function(data, resolve, reject){
    ext_opportunity_SubForm_opportunityProduct.setDetailExpand({expand:true});
    resolve(); //注意因为此处添加了阻塞性处理,所以需要监听 loaded的地方 resolve 进行后续的渲染处理。
});
  • 设置明细数据中字段的可见,只读,赋值,从业务类型的明细表格获取扩展点
const ext_opportunityProduct_SubForm_EntityType_opportunityProduct_886950 =
    new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_886950");

// 只读
ext_opportunityProduct_SubForm_EntityType_opportunityProduct_886950.setCellReadonly({
    rowIndex:  //数据行index
    itemApiKey:  //要修改的字段apiKey
    readonly: true/false
});
 
// 赋值
ext_opportunityProduct_SubForm_EntityType_opportunityProduct_886950.setCellValue({
    rowIndex:  //数据行index
    itemApiKey:  //要修改的字段apiKey
    value: //字段值 (文本或数值)
});

//可见
ext_opportunityProduct_SubForm_EntityType_opportunityProduct_886950.setCellVisible({
    rowIndex:  //数据行index
    itemApiKey:  //要修改的字段apiKey
    visible: true/false
});

//设置明细表格(包含tab)是否可见
ext_customEntity166__c_SubForm_customEntity167__c.setDetailTabeVisible({
    objectId:'1321131596169251',//明细表格的objectId
    visible: true/false//true可见、false不可见
})

//设置新建、编辑表单“保存并提交申请”按钮是否可见
const ext_account_Form_ButtonGroup = new xsyrpa.ButtonGroupExtensionPoint("account.Form#*#ButtonGroup");//按钮组
const ext_account_Form_saveAndSubmitApply = new xsyrpa.ButtonExtensionPoint("account.Form#*#saveAndSubmitApply");//按钮
ext_account_Form_ButtonGroup.on('detailButtonGroupLoaded', ()=>{
    ext_account_Form_saveAndSubmitApply.setVisible(value:true/false);//true可见、false不可见
})

[Web]系统级API示例

February 6, 2020

Author: 唐溢泓

网络请求操作

网络请求是个通用底层API,可以对销售易公开API发起请求,包括第三方可跨域请求

//网络请求实例
const ext_XRequest = new xsyrpa.XRequest();
//发起请求
ext_XRequest.request({
    url: "/rest/api/***",
    headers: {},
    method: "GET"
}).then((data) => { 
    //请求成功
}).catch((ex)=>{
    //请求失败
});

//XOQL的query string部分需要使用encodeURIComponent
ext_XRequest.request({
    url: `/rest/data/v2/query?q=${encodeURIComponent('select id, productName from product')}`,
    headers: {},
    method: 'GET'
})

//POST请求
ext_XRequest.request({
    url:'/data/v1/objects/***',
    headers: {
        Content-Type:'application/json'
    },
    method: 'POST',
    payload:{
        record:{}
    }
})




系统通知方法

通过SDK操作系统消息通知

  • 触发成功消息

// 实例化系统通知方法 
const notificationMessage = new xsyrpa.NotificationMessage();
// 触发成功的消息
notificationMessage.success({
    message: "保存成功"
});
  • 触发失败消息

//实例化系统通知方法
const notificationMessage = new xsyrpa.NotificationMessage();

//触发成功的消息
notificationMessage.error({
    message: "保存失败"
});
  • 触发警告消息

// 实例化系统通知方法 
const notificationMessage = new xsyrpa.NotificationMessage();
// 触发成功的消息
notificationMessage.warning({
    message: "警告"
});
  • 触发确认弹框

//实例化系统通知方法
const notificationMessage = new xsyrpa.NotificationMessage();

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

系统基础方法

  • 打开新窗口

const systemUtils = new xsyrpa.SystemUtils();

//打开Web新窗口
systemUtils.openWindow({url:"https://wwww.baidu.com"});

  • 打开弹出框

const systemUtils = new xsyrpa.SystemUtils();

//打开Web新窗口
ext_SystemUtils.openDialog({ url: "https://www.baidu.com", title: "百度示例", windowSize: 2 });
  • 刷新当前页

const systemUtils = new xsyrpa.SystemUtils();

//刷新当前页
systemUtils.refreshCurrentPage();

  • 显示隐藏IM消息

const systemUtils = new xsyrpa.SystemUtils();

//显示IM消息
systemUtils.setIMVisible(true);

//隐藏IM消息
systemUtils.setIMVisible(false);
  • 创建日程
// 实例化全局扩展点中的系统基础方法扩展点
const ext_SystemUtils = new xsyrpa.SystemUtils();

// 创建日程
ext_SystemUtils.openScheduleCreate({
   users:[{id:1, name:'张三'}, {id: 2,name: '李四'}]
});
  • 打开发送企业微信弹框
// 实例化全局扩展点中的系统基础方法扩展点
const ext_SystemUtils = new xsyrpa.SystemUtils();

// 打开和指定用户的企业微信对话框
ext_SystemUtils.openIMSDialog({
    id: 1,
    name: '张三'
});
  • 新建编辑实体Form
// 实例化全局扩展点中的系统基础方法扩展点
const ext_SystemUtils = new xsyrpa.SystemUtils();
 
// 打开实体新建弹框
ext_SystemUtils.openEntityDialog({
    entityApiKey: 'customize',  // 自定义实体传参 customize
    entityId: 1080313572917287, // 自定义实体id
    entityTypeId: 1080314194673700, //要新建的业务类型id
    postData:'',                 // 额外传参
    entityName: '自定义',         // 弹框显示的名字
    edit:false                   //  是否是编辑
});
 
// 打开新建商机明细弹框
ext_SystemUtils.openEntityDialog({
    edit: false,  //是否是编辑
    entityId: 18, //实体ID(商机明细)
    parentEntityId: 3,  //父实体(商机)ID
    parentDataId: 1091903814418476,  //商机数据ID
    entityTypeId: 886943,  //商机数据业务类型ID
    productFamilyId:'',   //价格表ID
    hasDetailData:1,  //商机上是否已存在明细数据
    entityApiKey:'opportunityproduct',
    entityName: 'Opportunity Products'
})
  • 获取当前登入用户的信息
const ext_SystemUtils = new xsyrpa.SystemUtils();
ext_SystemUtils.currentUser().then((user) => {
    console.log(user)
})
  • 设置页面按钮
const ext_SystemUtils = new xsyrpa.SystemUtils("SystemUtils");
//visible 按钮是否显示
//url 点击按钮的跳转url
//text 按钮文字
//tipText 按钮的提示文字
//bgColor 按钮背景色
//textColor 文字颜色
ext_SystemUtils.invokeAsync('setCRMPgBtn',{'visible': true,'url': 'https://www.baidu.com/','text': '测试','tipText': '测试','bgColor': '#f00','textColor': '#00f'});

[Web]表单页代码示例

February 5, 2020

Author: 唐溢泓、江炜

表单

表单主要可以实现字段的操作


//获取表单实例
const ext_customEntity65__c_Form_ = new xsyrpa.FormExtensionPoint("customEntity65__c.Form#*#");
//表单加载完成
ext_customEntity65__c_Form_.on("loaded", async (data) => {
    //获取新建表单的地址
    const ext_account_form_address = new xsyrpa.FormTextInputExtensionPoint("account.form#*#address");
    //设值
    ext_account_form_address.setValue("上海,北京");
    //设置只读
    ext_account_form_address.setReadOnly(true);
    //设置必填
    ext_account_form_address.setRequired(true);
    //设置可见
    ext_account_form_address.setVisible(true);
    //设置字段错误提醒
    ext_account_form_address.setError("错误信息");
    //设置表单的placeholder
    ext_account_form_address.setPlaceholder("新的placeholder");
    //设置样式
    ext_account_form_address.setInlineStyle({
      //selector是css选择器
      //了解css选择器: https://developer.mozilla.org/zh-CN/docs/Glossary/CSS_Selector
      selector: ".ui-spinner",
      style: { "border": "1px solid red", "border-radius": "4px" },
    });

    //当数据发现变化时
    ext_account_form_address.on("onChange", (data) => {

    });
});


//获取表单实例
const ext_customEntity65__c_Form_ = new xsyrpa.FormExtensionPoint("customEntity65__c.Form#*#");
//表单已加载
ext_customEntity65__c_Form_.on("loaded", async (data) => {
    //获取新建表单按钮组
    const ext_customEntity65__c_Form_ButtonGroup = new xsyrpa.ButtonGroupExtensionPoint("customEntity65__c.Form#*#ButtonGroup");
    const newButton = await ext_customEntity65__c_Form_ButtonGroup.addButton({
        extId: "newButtonInForm",
        text: "新按钮"
    });

    newButton.on("onClick", () => {

    });

    //获取新建按钮的实例
    const ext_customEntity65__c_Form_draft = new xsyrpa.ButtonExtensionPoint("customEntity65__c.Form#*#draft");
    //改变按钮文字
    ext_customEntity65__c_Form_draft.setText("新文本");
    //设置可见
    ext_customEntity65__c_Form_draft.setVisible(true);
});

//保存前触发
ext_customEntity65__c_Form_.on("beforeSave", (data, resolve, reject) => {
    //对数据进行操作,或者弹出确认框,通过resolve表示继续执行保存,reject表示不再执行保存
    //resolve();
    //reject();
});


明细的扩展点列表示意图(以商机明细为例, 自定义实体相同)



明细Picker自定义

//商机明细自定义picker
//创建商机明细扩展实例
const ext_opportunityProduct_Form_opportunityProduct = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.Form#*#opportunityProduct-919228631532061");
//系统方法实例
const ext_SystemUtils = new xsyrpa.SystemUtils();
//eg.1 监听商机明细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});
    });
});
 
//eg.2 监听商机明细数据修改,自定义校验并提示
ext_opportunityProduct_Form_opportunityProduct.on('rowDataChanged', function(rowData){
    //数量大于20时
    if(rowData.data.amount > 20){
        //错误提示
        ext_opportunityProduct_Form_opportunityProduct.setCellError({rowIndex:rowData.index, apiKey:'amount', messages:'数量不能超过20'});
    }
});
 
 
/*
    自定义页面
*/
//自定义页面 传值 关闭picker
//自定义按钮,点击时
function(){
    let msg = {
      isvData: 1,2,3 //选择的数据ids,
      doClose: true
    };
    window.top.postMessage(msg, '*');
}

商机设置必须含有明细,列表自定义搜索条件

//商机表单中的商机明细实体
const ext_opportunity_SubForm_opportunityProduct = new xsyrpa.FormSubEntityTableExtensionPoint("opportunity.SubForm#*#opportunityProduct");
//商机列表页
const ext_opportunity_ListPage_ListPage = new xsyrpa.EntityListPageExtensionPoint("opportunity.ListPage#*#ListPage");
//监听明细load完成
ext_opportunity_SubForm_opportunityProduct.on('loaded', async function(){
    //设置商机明细实体保存时必须有明细
    ext_opportunity_SubForm_opportunityProduct.allowEmptyDetailData({entityApiKey:'opportunityProduct', enabled:true});
     
    //列表上增加一个普通按钮
    const newButton = await ext_opportunity_ListPage_ListPage.addButtonItem({
        extId:"newButtonId",
        text:"新按钮"
    });
    //普通按钮点击时 向列表增加一个筛选条件 进行搜索
    newButton.on("onClick", function(){
        var conditions = [{"id":"11","item":"26905910","type":"1","value":"123"},{"id":"12","item":"26905910","type":"1","value":"testr5"}]
        ext_opportunity_ListPage_ListPage.addFilterConditions({expression:"11 OR 12", conditions:conditions, refresh:true});
        //ext_opportunity_ListPage_ListPage.refreshData();
    });
    /*
        列表搜索API说明
        1. 通过addFilterConditions 向列表传递搜索条件为替换模式。
           即: 每次执行筛选的条件均为 列表当前视图系统自带筛选条件 AND API传递条件。
        2. API传递条件中的参数:
           item 实体字段itemId
           type 表达式运算符
                3 => in
                10 => equal
                12 => fromTo (区间, 如数值型 在10~20之间, {item:xxx, type:12, value:"10,20"})
           value 表达式右值
           id 当使用expression描述多个条件之间的关系时使用
            (建议使用10以上值作为id, 因为系统列表视图中有的会带有默认条件中含有id(如我负责的XXX),或自定义检索视图本身带有公式时。)
        3. expression
           多个条件间的关系公式。如果是空则条件之间默认为 AND 关系。
           API传递此参数后, 融合系统中现有筛选条件时
           系统中没有expression, 直接使用。
           系统中有expression,  System_expression + 'AND ('  + expression + ')' 组合使用。
           鉴于2中提到的id冲突问题,expression参数传递时 示例 "11 OR 12";
    */
      
 
});

批量新增编辑商机明细及全量数据获取

/*商机新建编辑*/
ext_opportunity_Form_.on('beforeSave', (data, resolve, reject)=>{
    var needConfirm = false;
    console.log(data);
    var jsonEntity =  JSON.parse(data.detailEntityMap);
     
    //编辑时,明细数据是增量获取修改过的字段
    //所以需要在明细表格的扩展点上调用getDetailData来获取全部数据。
    const ext__SubForm_opportunityProduct = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm#*#opportunityProduct");
    const fullData = await ext__SubForm_opportunityProduct.getDetailData({fullData:true});
 
 
    //...后续逻辑
});
 
/*商机明细新建编辑(商机详情页明细相关上新建编辑,只有子时)*/
//表单和商机新建编辑不一样
const ext_opportunityProduct_Form_ = new xsyrpa.FormExtensionPoint("opportunityProduct.Form#*#");
ext_opportunityProduct_Form_.on('beforeSave', async function(data,resolve, reject){
    console.log("原生数据", data);
    const ext__SubForm_opportunityProduct = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm#*#opportunityProduct");
    const fullData = await ext__SubForm_opportunityProduct.getDetailData({fullData:true});
    console.log("全明细数据", fullData);
    //后续代码
});

明细设置字段可编辑及触发计算

//设置 标准价格可编辑, 编辑时触发计算示例
//报价单 (分步交互)
const ext_quote_CPQPriceSetsExtensionPoint = new xsyrpa.CPQPriceSetsExtensionPoint("quote_CPQPriceSetsExtensionPoint");
//监听价格配置页,行数据添加后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterAddDetail', function(){
    //获取明细数据
    ext_quote_CPQPriceSetsExtensionPoint.getDetailData().then(function(data){
        for(var i = 0; i<data.length;i++){
            //遍历数据找到 产品名称为  B3  的产品
            if(data[i] && data[i]['quotationDetailEntityRelProduct-label'] === "B3"){
                //设置  priceUnit (标准价格) 为可编辑
                ext_quote_CPQPriceSetsExtensionPoint.setCellEditable({detailUuid: data[i].detailUuid, detailId: data[i].id, itemApiKey: 'priceUnit', editable:true});
            }
        }
    });
});
//监听 明细数据编辑后事件
ext_quote_CPQPriceSetsExtensionPoint.on('afterEditDetail', function(data){
    if(data.itemApiKey == 'priceUnit'){
        //判断修改 标准价格时 获取编辑的当条明细数据
        ext_quote_CPQPriceSetsExtensionPoint.getDetailData({detailUuid: data.detailUuid}).then(function(detail){
            //触发计算 (由于系统默认不能修改标准价格,因此用销售单价触发计算)
            ext_quote_CPQPriceSetsExtensionPoint.detailCalculate({detailUuid: detail.detailUuid, detailId: detail.id, itemApiKey:'price', newValue: detail.price});
        });
    }
});
 
//商机
//创建商机明细某业务类型表格实例
const ext_opportunityProduct_SubForm_EntityType_opportunityProduct_549175303520276 = new xsyrpa.FormSubEntityTableExtensionPoint("opportunityProduct.SubForm.EntityType#*#opportunityProduct_549175303520276");
//监听行数据添加后事件
ext_opportunityProduct_SubForm_EntityType_opportunityProduct_549175303520276.on('afterAddDetail', function(data){
    console.log(data.data);
    //判断产品名称
    if(data.data.productId.label === 'B3' || data.data['productId-label'] == 'B3'){
       //设置字段可编辑
        ext_opportunityProduct_SubForm_EntityType_opportunityProduct_549175303520276.setCellEditable({
            rowIndex: data.index,
            cellIndex:'',
            itemApiKey: 'standardPrice',
            editable:true
        });
    }
});
//监听行数据编辑后事件
ext_opportunityProduct_SubForm_EntityType_opportunityProduct_549175303520276.on('rowDataChanged', function(data){
    //判断编辑的字段
    if(data.itemApiKey === 'standardPrice'){
        //触发计算
        ext_opportunityProduct_SubForm_EntityType_opportunityProduct_549175303520276.detailCalculate({
            rowIndex: data.index,
            cellIndex:'',
            itemApiKey: 'priceUnit',
            newValue: data.data.priceUnit
        })
    }
});

关联字段使用自定义数据选择页面


const ext_SystemUtils = new xsyrpa.SystemUtils();
const ext_TestButton__c_Form_Account__c = new xsyrpa.FormRelatedFieldExtensionPoint("TestButton__c.Form#*#Account__c");

//eg.1 监听关联字段picker点击+号
ext_TestButton__c_Form_Account__c.on("pickerHookTrigger",(data, resolve, reject)=>{
    //打开Dialog, 链接到自定义页面
    //自定义页面调用Api等方式(可将data传入作为参数)获取信息
    ext_SystemUtils.openDialog({
        url: 'https://www.reynanote.com/?id=963469313770032',
        windowSize:2,
        title: "自定义选择实体"
    }).then(function(data){
        //返回选中实体数据
            resolve(data);
    });
});



[Web]列表页代码示例

February 4, 2020

Author: 郑颍丽、江炜

列表页

普通按钮扩展


const NEWBTNID = "newButtonId";
const NEWCREATIONBTNID = "newCreationButtonId";

//获取列表页扩展实例
const ext_opportunity_ListPage_ListPage = new xsyrpa.EntityListPageExtensionPoint(“opportunity.ListPage#*#ListPage");

//获取“导入销售机会”按钮扩展实例
const ext_opportunity_ListPage_import_Button = new xsyrpa.ButtonExtensionPoint("opportunity.ListPage#*#import.Button”);

//列表页初始化完成 -- 生命周期事件inited
ext_opportunity_ListPage_ListPage.on("inited", async () => {

    //隐藏导入销售机会按钮
    ext_opportunity_ListPage_import_Button.setVisible(false);


    //替换标准的 新建 按钮
    const newCreationButton = await ext_opportunity_ListPage_ListPage.replaceCreationButton({
        extId:NEWCREATIONBTNID,
        text:"新建逻辑"
    });
    newCreationButton.on("onClick",()=>{
        //按钮新逻辑
    });



    //新增标准按钮和点击事件
    const newButton = await ext_opportunity_ListPage_ListPage.addButtonItem({
        extId: NEWBTNID,
        text: "新按钮"
    });
    newButton.on("onClick",()=>{
        //新按钮点击事件
    });

});

批量按钮扩展


const NEWBTACHBTNID = "newBatchButtonId";

//获取列表页扩展实例
const ext_opportunity_ListPage_ListPage = new xsyrpa.EntityListPageExtensionPoint(“opportunity.ListPage#*#ListPage");

//列表页初始化完成 -- 生命周期事件inited
ext_opportunity_ListPage_ListPage.on("inited", async () => {

    //新增批量按钮
       const newBatchButton = await ext_opportunity_ListPage_ListPage.addBatchButtonItem({
        extId: NEWBTNID,
        text: "新批量按钮"
    });
    newBatchButton.on("onClick",async ()=>{
        //获取批量选中Ids
        const ids = await ext_opportunity_ListPage_ListPage.getSelectedIds();
    });

});

列表页

// 实例化列表页扩展点(订单列表为例)
const ext_order_ListPage_ListPage = new xsyrpa.EntityListPageExtensionPoint("order.ListPage#*#ListPage");
 
// 列表页加载完成
ext_order_ListPage_ListPage.on('inited', ()=>{
   //无数据传出
});
 
//获取列表选中的数据Id
ext_order_ListPage_ListPage.getSelectedIds().then((data)=>{
  // data 为 ids 数组
});
 
// 刷新列表表格部分
ext_order_ListPage_ListPage.refreshData();
 
// 向表格传递筛选条件并刷新
// 每次传递的筛选条件是覆盖之前的, 但会和手动操作的条件以及视图的自带条件叠加后查询
ext_order_ListPage_ListPage.addFilterConditions({
   conditions,  // 条件集合
   expression  // 高级公式
});

//列表页所有字段扣框编辑禁用(true全部禁用,false无响应)
ext_order_ListPage_ListPage.invokeAsync('setEntityItemReadonly',true)
/*
    列表搜索API说明
    1. 通过addFilterConditions 向列表传递搜索条件为替换模式。
        即: 每次执行筛选的条件均为 列表当前视图系统自带筛选条件 AND API传递条件。
    2. API传递条件中的参数:
        item 实体字段itemId
        type 表达式运算符
            3 => in (文本型字段时,为like模糊匹配)
            10 => equal
            12 => fromTo (区间, 如数值型 在10~20之间, {item:xxx, type:12, value:"10,20"})
        value 表达式右值
        id 当使用expression描述多个条件之间的关系时使用
        (建议使用10以上值作为id, 因为系统列表视图中有的会带有默认条件中含有id(如我负责的XXX),或自定义检索视图本身带有公式时。)
    3. expression
        多个条件间的关系公式。如果是空则条件之间默认为 AND 关系。
        API传递此参数后, 融合系统中现有筛选条件时
        系统中没有expression, 直接使用。
        系统中有expression,  System_expression + 'AND ('  + expression + ')' 组合使用。
        鉴于2中提到的id冲突问题,expression参数传递时 示例 "11 OR 12";
*/

[Web]详情页代码示例

February 3, 2020

Author: 郑颍丽、江炜

详情页

详情页扩展有头部按钮, 资料页表单, 商机推进组件, 相关列表页按钮 等 其中按钮icon地址:Breeze Icons 图标名字规则: name-theme, 其中主题theme可以为空,默认使用Outlined主题, 例如: comment_32-filled, comment_32.


const CUSTOMBTNID = "CUSTOMBTNID";

//获取详情页头部按钮组扩展点实例
const detailPageButtonGroup = new xsyrpa.ButtonGroupExtensionPoint("customEntity78__c.DetailPage#*#Header_ButtonGroup");
detailPageButtonGroup.on('detailButtonGroupLoaded', (data) => {
     //新增按钮到头部按钮组中
    detailPageButtonGroup.addButton({
        extId: CUSTOMBTNID,
        text: "新按钮"
    }).then((newBtn) => {
        //新增按钮成功
        newBtn.on("onClick", () => {
            //新按钮事件 
        });
    });

    //获取编辑按钮实例
    const editButton = new xsyrpa.ButtonExtensionPoint("customEntity78__c.DetailPage#*#_editCustomize_button");
    //隐藏编辑按钮
    editButton.setVisible(false);
});

相关列表按钮代码示例

const ext_AppPageLifeCycle = new xsyrpa.PageExtensionPoint("AppPageLifeCycle");

//页面加载时设置sessionStorage
ext_AppPageLifeCycle.on("setStorage", function(data, resolve) {
    window.sessionStorage.setItem('maskForHSBC',JSON.stringify(data));
});

//应用加载完毕
ext_AppPageLifeCycle.on("loaded", () => {

    //获取文档相关列表按钮组
    const ext_customEntity78__c_DetailPage__ReferList_1009_ButtonGroup = new xsyrpa.ButtonGroupExtensionPoint("customEntity78__c.DetailPage#*#_ReferList_1009_ButtonGroup");
    //新增按钮到文档相关列表
    ext_customEntity78__c_DetailPage__ReferList_1009_ButtonGroup.addButton({
        extId:"buttonid",
        icon:"comment_32",
        text:""
    });
    //隐藏相关列表详细数据操作按钮组(true隐藏,false显示)
    ext_customEntity78__c_DetailPage__ReferList_1009_ButtonGroup.invokeAsync('removeButton',true)

})


//获取资料页表单实例
const ext_form331606 = new xsyrpa.FormExtensionPoint("form331606");
ext_form331606.on("loaded",(formData)=>{
    //打印表单数据
    console.log(formData);
    //获取资料页字段"传真"
    const ext_entityInfo_account_fax = new xsyrpa.FormInlineItemExtensionPoint("entityInfo_account.fax");
    //设置必填
    ext_entityInfo_account_fax.setRequired(true);

    //设置可见
    ext_entityInfo_account_fax.setVisible(true);

    //设置只读
    ext_entityInfo_account_fax.setReadOnly(true);
});

详情页头部按钮组

详情页暂时还未有整体的生命周期扩展点。

如果想获取详情页的数据id, 可以从头部按钮组的扩展点上获取。

  • 头部按钮组示例
const ext_order_DetailPage_Header_ButtonGroup = new xsyrpa.ButtonGroupExtensionPoint("order.DetailPage#*#Header_ButtonGroup");
ext_order_DetailPage_Header_ButtonGroup.on('detailButtonGroupLoaded', (data) => {
    // 传出data为
    /*
      {
         entityId // 实体id
         recordId // 数据id
      }
    */
 
    //之后可以进行调用openApi或控制系统按钮的隐藏等(使用方法见已公开文档)
})
  • 报价单详情页根据审批状态隐藏打印按钮
const ext_quote_DetailPage_Header_ButtonGroup = new xsyrpa.ButtonGroupExtensionPoint("quote.DetailPage#*#Header_ButtonGroup"); //标价单详情页头部按钮组
const ext_quote_DetailPage__printCustomize_button = new xsyrpa.ButtonExtensionPoint("quote.DetailPage#*#_printCustomize_button"); //报价单详情页打印按钮
ext_quote_DetailPage_Header_ButtonGroup.on('detailButtonGroupLoaded', (data)=>{
    console.log(data);
    //data.recordId, data.entityId
    //调用OpenApi 获取审批状态
    //隐藏打印按钮
    ext_quote_DetailPage__printCustomize_button.setVisible(false);
})

详情页-资料组件-分割线隐藏(以商机报备为例)

资料页分割线

资料页分割线扩展点

资料分割线显示与隐藏


const ext_opportunity_register_DetailPage_opportunity_register_splitline = new xsyrpa.FormItemSectionExtensionPoint("opportunity_register.DetailPage#*#opportunity_register_splitline");
/**
 * @param  true 显示 false 隐藏
 * */
ext_opportunity_register_DetailPage_opportunity_register_splitline.setVisible(true) //显示分割线

web左侧菜单配置


const ext_AppLeftMenu = new xsyrpa.LeftMenuExtensionPoint("AppLeftMenu");
/**
     * 菜单项显示、隐藏、文本替换
     * itemKey:  菜单项的唯一标识(菜单项的menuId)
     * text: 替换的文案,不传不替换
     * visible:设置菜单项是否显示
     * 例如:[{itemKey: '40', text: "电话台", visible: true}]。
     * 这个规则意义:menuid为40的菜单项文案更改为配置显示。
*/
ext_AppLeftMenu.setMenuItemsConfig([{itemKey: '357719', text: '2222', visible: true}])

[Web]调试RPA JS扩展代码

February 1, 2020

Author: 傅腾

在Chrome插件中调试RPA JS扩展代码

  1. 拉取扩展点,编写RPA JS扩展代码
  2. 点击"预览"按钮,把编写的JS扩展代码注入到运行时
  3. 点击"Sources"页签,在"BRZRPAWORKER"下,选择一个以uuid为名字的文件
  4. 在这个文件中可以看到刚才编写的JS扩展代码,在需要调试的行上加断点

补充1. 也可以在JS扩展代码中输入debugger,点击"预览"按钮,当运行到扩展点代码时,会自动进入断点

点我了解debugger

补充2. 用webpack打包发布后的代码,可以在webpack://文件夹下找到相应的源码

← PrevNext →
Copyright © 2021 销售易