
# 开发脚本
针对业务逻辑比较复杂的场景，可以使用脚本（Script）能力，在线开发TypeScript脚本，完成灵活复杂的业务逻辑。
#### 背景信息
平台的脚本引擎采用TypeScript语言；脚本执行时，TypeScript语言会被翻译成JavaScript语言，由JavaScript引擎执行。
在JavaScript es5的官方标准库外，平台还扩展了10+预置标准库（即预置API），帮助您更高效地开发脚本，有关系统预置的标准库说明请参见[脚本中预置的API](https://support.huaweicloud.com/api-astrozero/astrozero_api_00100.html)。
#### 场景描述
本节以基于[开发对象](https://support.huaweicloud.com/devg-isdp-Intel/seddev_017.html)中创建的对象，开发一个新脚本（addAccruedLeaveRecord1），用于添加对象的数据为例，描述开发脚本的过程。其中，脚本中引入智能排班模型BO中脚本的方法记录操作日志。
#### 操作步骤
1. 创建脚本。 
   1. 如[图1]所示，在应用的开发页面，选择存放脚本的目录（控制逻辑），单击目录对应的![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565264625.png)，选择"脚本"。
      图1创建脚本   
      ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565384517.png) 
   
   2. 在弹出的"新增脚本"页面，如[图2]所示，选择创建一个新脚本，输入脚本"名称"为"addAccruedLeaveRecord1"，"模板"选择"空脚本"，单击"添加"。
      创建完成后，自动进入编辑页面。
      图2新增脚本   
      ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001514264318.png "点击放大") 
   
   
   
   
2. 编辑脚本。 
   脚本示例如下，脚本的说明请参见示例的备注内容。
   ```
   //引入该脚本依赖的标准库或者其他模块。db、date是系统预置的标准库；ISDP__commApiForAppcube是引入的智能排班模型BO中一个脚本。
   import * as db from 'db';               //引入处理对象的标准库
   import { format, now } from 'date';     //引入处理时间的标准库中的时间转换为字符串和获取当前时间
   import AppCubeApi from './ISDP__commApiForAppcube';    //引入脚本中的方法AppCubeApi
   //实例化
   const appcube = new AppCubeApi();
   const Func = "batchAddOperationInfo";
   const Success = 'success';
   const Add = 'add';
   //定义入参结构，所有的输入参数必须封装在一个class中，作为实例成员，示例中被封装为Input。
   @action.object({ type: "param" })
   export class Input {
       @action.param({ type: "String", description: "人员账号", required: false })
       personCode: string;
       @action.param({ type: "String", description: "人员名称", required: false })
       personName: string;
       @action.param({ type: "String", description: "班次id", required: false })
       shiftId: string
       @action.param({ type: "String", description: "班次名称", required: false })
       shiftName: string;
       @action.param({ type: "String", description: "召回开始时间", required: true })
       recallStart: string;
       @action.param({ type: "String", description: "召回结束时间", required: true })
       recallEnd: string;
       @action.param({ type: "String", description: "审批流名称", required: true })
       bpmName: string
       @action.param({ type: "String", description: "审批流标签", required: true })
       bpmLable: string;
       @action.param({ type: "String", description: "审批流实例id", required: true })
       bpmInstanceId: string;
       @action.param({ type: "String", description: "召回原因", required: false })
       recallReason: string;
   }
   //定义出参结构，所有的输出参数必须封装在一个class中，作为实例成员，示例中被封装为Output。
   @action.object({ type: "param" })
   export class Output {
       @action.param({ type: "String", description: "错误码", isCollection: false })
       statusCode: string;
       @action.param({ type: "String", description: "错误描述", isCollection: false })
       message: string;
   }
   //定义该脚本中使用到的ISDP__accruedLeaveApplicationRecord1__CST对象
   @useObject(['ISDP__accruedLeaveApplicationRecord1__CST'])
   //定义方法，进行数据库操作
   //示例中，使用action.method函数标识Action的调用方法AddAccruedLeaveRecord.run，表明调用脚本时从此方法入口，其输入、输出参数就是前面定义的Input和Output。
   //在一个脚本文件里面，action.method只能使用一次
   @action.object({ type: "method" })
   export class AddAccruedLeaveRecord {
       @action.method({ input: "Input", output: "Output", description: "添加积假申请记录" })
       run(input: Input): Output {
           let output = new Output();
           try {
               let s = db.dynamicObject('ISDP__accruedLeaveApplicationRecord1__CST');
               let start = new Date(input.recallStart);
               let end = new Date(input.recallEnd);
               let accruedLeaveThisTime = (end.getTime() - start.getTime()) / 10000 / 60 / 6;
               console.log("accruedLeaveThisTime", accruedLeaveThisTime)
               let date = new Date();
               let accruedLeaveCode = date.getFullYear() + "" + (date.getMonth() + 1) + "" + date.getDate() + "" + date.getHours() + "" + date.getMinutes() + "" + date.getSeconds() + "" + date.getMilliseconds();
               console.log("date", accruedLeaveCode)
               //insert内容
               let record = {
                   "ISDP__personCode__CST": input.personCode,
                   "ISDP__personName__CST": input.personName,
                   "ISDP__shiftId__CST": input.shiftId,
                   "ISDP__shiftName__CST": input.shiftName,
                   "ISDP__recallStart__CST": input.recallStart,
                   "ISDP__recallEnd__CST": input.recallEnd,
                   "ISDP__accruedLeaveThisTime__CST": accruedLeaveThisTime.toFixed(2) + "",
                   "ISDP__accruedLeaveCode__CST": accruedLeaveCode,
                   "ISDP__bpmName__CST": input.bpmName,
                   "ISDP__bpmLable__CST": input.bpmLable,
                   "ISDP__bpmInstanceId__CST": input.bpmInstanceId,
                   "ISDP__recallReason__CST": input.recallReason,
                   "ISDP__approvalStatus__CST": "0",
                   "ISDP__submitTime__CST": format(date, 'yyyy-MM-dd HH:mm:ss'),
                   "ISDP__completeTime__CST": "-",
                   "ISDP__deleteFlag__CST": "0"
               }
               s.insert(record);
               appcube.addOperLog(Add, Func, Success, '新增积假申请记录成功', 'ISDP__accruedLeaveApplicationRecord1__CST');   //调用引入的AppCubeApi方法，记录操作日志
               output.statusCode = "0";
               output.message = "成功";
           } catch (error) {
               output.statusCode = "1";
               output.message = "失败";
           }
           return output;
       }
   }
   ```
   
   
3. 保存脚本。 
   如[图3]所示，单击页面上方的![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565384521.png)，保存脚本。
   图3保存脚本   
   ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565024369.png)
   
   
4. 测试脚本。 
   1. 如[图4]所示，单击页面上方的![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565264613.png)，在页面底部显示测试窗口，如[图5]所示。
      图4运行测试脚本   
      ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565024353.png)
      图5测试窗口   
      ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001514424286.png "点击放大") 
   
   2. 在测试窗口中，"输入参数"页签下，输入入参，单击![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001514264310.png)。
      入参示例：
      ```
      {
          "personCode":"111",
          "personName":"chen",
          "shiftId":"222",
          "shiftName":"yong",
          "recallStart":"2023-03-01",
          "recallEnd":"2023-03-02",
          "bpmName":"admin",
          "bpmLable":"a",
          "bpmInstanceId":"333",
          "recallReason":"remark"
      }
      ```
      
   
   3. 查看"输出参数"页签下，结果是否符合预期。
      ```
      {
          "message": "成功",
          "statusCode": "0"
      }
      ```
      
   
   4. 查看"日志"页签下，输出日志。
      ```
      0330 10:44:28.362|debug|vm[1795]>>> Build #AppCube Core 23.2.0spc1 amd64
      Built on 2023-03-09 20:10:11 
      Commit #80465c38e2
      0330 10:44:28.364|debug|vm[1795]>>> node:  28
      0330 10:44:28.365|debug|vm[1795]>>> script:  ISDP__addAccruedLeaveRecord1__1.0.1 AddAccruedLeaveRecord.run
      0330 10:44:28.367|debug|vm[1795]>>> locale:  zh_CN
      0330 10:44:28.368|debug|vm[1795]>>> os timezone:  Local
      0330 10:44:28.370|debug|vm[1795]>>> user timezone:  Local
      0330 10:44:28.371|debug|vm[1795]>>> organization timezone:  (GMT+08:00) China Standard Time (Asia/Shanghai)
      0330 10:44:28.373|debug|vm[1795]>>> load module ISDP__addAccruedLeaveRecord1__1.0.1 (ISDP__addAccruedLeaveRecord1_wrapper.ts:2)
      0330 10:44:28.374|debug|vm[1795]>>> load module db (ISDP__addAccruedLeaveRecord1.ts:2)
      0330 10:44:28.376|debug|vm[1795]>>> load module date (ISDP__addAccruedLeaveRecord1.ts:3)
      0330 10:44:28.377|debug|vm[1795]>>> load module ISDP__commApiForAppcube__1.1.0 (ISDP__addAccruedLeaveRecord1.ts:4)
      0330 10:44:28.378|debug|vm[1795]>>> load module http (ISDP__commApiForAppcube.ts:3)
      0330 10:44:28.380|debug|vm[1795]>>> load module ISDP__ErrorCodeList__1.1.0 (ISDP__commApiForAppcube.ts:6)
      0330 10:44:28.381|debug|vm[1795]>>> load module ISDP__AddLog__1.0.1 (ISDP__commApiForAppcube.ts:7)
      0330 10:44:28.382|debug|vm[1795]>>> load module ISDP__validator__1.0.1 (ISDP__AddLog.ts:3)
      0330 10:44:28.384|debug|vm[1795]>>> load module context (ISDP__validator.ts:2)
      0330 10:44:28.385|debug|vm[1795]>>> load module sys (ISDP__validator.ts:5)
      0330 10:44:28.387|debug|vm[1795]>>> accruedLeaveThisTime 24 (ISDP__addAccruedLeaveRecord1.ts:61)
      0330 10:44:28.389|debug|vm[1795]>>> date 2023330104428389 (ISDP__addAccruedLeaveRecord1.ts:64)
      0330 10:44:28.421|debug|vm[1795]>>> resource limit usage:
          number of RequestSOQLQueriesAmount: 0
          number of RequestSOQLRowsAmount: 0
          number of RequestSOSLQueriesAmount: 0
          number of RequestSOSLRowsAmount: 0
          number of RequestDMLStatementsAmount: 2
          number of RequestDMLRowsAmount: 2
          number of RequestCallOutsAmount: 0
          number of RequestEmailSendsAmount: 0
          number of RequestEventSendsAmount: 0
      ```
      
   
   5. 如[图6]所示，单击右上角![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565024357.png)，进入控制台。
      图6控制台   
      ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565264629.png) 
   
   6. 如[图7]所示，在"对象管理"页签中，输入查询语句（select \* from ISDP__accruedLeaveApplicationRecord1__CST），查询数据。
      图7查询数据   
      ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565184265.png "点击放大") 
   
   
   
   
5. 启用脚本。 
   如[图8]所示，单击页面上方的![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001565024361.png)，启用脚本。
   图8启用脚本   
   ![](https://support.huaweicloud.com/devg-isdp-Intel/zh-cn_image_0000001514264306.png)
   ![](https://support.huaweicloud.com/devg-isdp-Intel/public_sys-resources/note_3.0-zh-cn.png)
   脚本开发完成后，可以封装成一个接口，供调用，具体请参见[如何自定义调用脚本的URL](https://support.huaweicloud.com/usermanual-astrozero/astrozero_05_0054.html)。
   
   
 
