华为云用户手册

  • 实现“根据设备编码自动加载工单其他信息” 在“我的应用”中,单击“设备维修管理系统”,进入应用。 单击打开“HW__createWorkOrder”页面。 添加页面事件代码。 在“设计视图”中,选中最外层的“页面”,也可以直接单击组件导航,快速定位。 在右侧“事件”页签中,单击“加载”后的“+”,为页面添加事件代码。 在“添加动作”弹窗的“自定义动作”中,输入如下事件代码。 $model.ref('equipmentOptions').setData({inputParam:{}}); $model.ref('equipmentOptions').run().then(function(response){ if(response.equipList){ $model.ref("equipmentList").setData(response.equipList); } }); 单击“创建”,退出事件编排窗口。
  • 实现“显示设备详细信息” 通过定义“基本信息”区域“设备名称”下拉框的“数据改变”事件,可以实现根据所选设备,在“设备详情”区域显示设备信息。 在“HW__createWorkOrder”页面中,选中“设备名称”下拉框。 图1 添加“数据改变”事件代码 在右侧“事件”页签中,单击“数据改变”后的“+”。 在“添加动作”弹窗的“自定义动作”中,输入如下事件代码。 脚本中加粗斜体内容请替换为实际的命名空间前缀。 let equipment = $model.ref("basicInfo").getData(); let equipmentId = equipment.HW__equipmentId__ CS T; let queryEquipParam = {"id" : equipmentId}; $model.ref('equipmentOptions').setData({inputParam: queryEquipParam}); $model.ref('equipmentOptions').run().then(function (response) { if (response.equipment) { $model.ref("equipmentInfo").setData(response.equipment); } }); 单击“创建”,退出事件编排窗口。
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 在“WorkOrder”目录中,鼠标放在“Page”上,单击界面上出现的“+”,在弹出菜单中选择“标准页面”。 在“标签”和“名称”文本框中输入“createWorkOrder”,单击“添加”。 当编辑已有标准页面时,为防止编辑时多人篡改,编辑前请单击进行锁定。 在标准页面的“设计视图”下,单击页面底部的“模型视图”页签,切换到“模型视图”。 图3 切换模型视图 定义模型“basicInfo”。 在模型视图页面,单击“新增模型”。 添加自定义模型,模型名称“basicInfo”,单击“下一步”。 单击“新增节点”,新增设备ID字段“HW__equipmentId__CST”,并设置字段类型“SingleSelect”,加粗斜体内容请替换为实际命名空间前缀。 依次增加表2中列出的字段名称,单击“下一步”,再单击“确定”。 图4 新增节点字段 加粗斜体内容请替换为实际命名空间前缀。 表2 新增basicInfo模型的节点字段 字段名称 字段类型 字段描述 HW__equipmentId__CST(上一步已添加) SingleSelect 设备ID HW__title__CST Text 工单标题 createdDate DateTime 创建时间 HW__type__CST SingleSelect 工单类型 HW__priority__CST SingleSelect 工单优先级 HW__description__CST TextArea 工单备注说明 HW__faultPhenomenon__CST Text 故障现象说明 HW__customer__CST Text 客户接口人 HW__recoveryTime__CST DateTime 客户要求故障恢复时间 HW__source__CST Text 工单来源 HW__arriveTime__CST DateTime 客户要求工程师到达现场时间 单击页面上方的,保存设置。 定义模型“equipmentList”。 在模型视图页面,单击“新增模型”。 添加自定义模型,模型名称“equipmentList”,单击“下一步”。 单击“下一步”,再单击“确定”。 单击页面上方的,保存设置。 定义模型“equipmentInfo”。 在模型视图页面,单击“新增模型”。 添加自定义模型,模型名称“equipmentInfo”,单击“下一步”。 单击“新增节点”,依次新增表3中列出的字段名称,单击“下一步”,再单击“确定”。 加粗斜体内容请替换为实际命名空间前缀。 表3 新增equipmentInfo模型的节点字段 字段名称 字段类型 字段描述 name Text 设备名称 HW__equipmentSN__CST Text 设备编码 HW__equipmentBrand__CST Text 设备品牌 HW__equipmentModel__CST Text 设备型号 HW__fullAddress__CST Text 设备完整地址 单击页面上方的,保存设置。 定义模型“equipmentOptions”。 在模型视图页面,单击“新增模型”。 添加服务模型,模型名称“equipmentOptions”,单击“下一步”。 设置服务类型为“公共接口”,“项目”选择“设备维修管理系统”,公共接口为“equipmentSelectListQuery”,即创建“查询设备列表”脚本中定义的脚本“equipmentSelectListQuery”对应的公共接口,单击“下一步”,再单击“确定”。 图5 选择服务 单击页面上方的,保存设置。 定义模型“setInstanceId”。 在模型视图页面,单击“新增模型”。 添加服务模型,模型名称“setInstanceId”,单击“下一步”。 设置服务类型为“公共接口”,“项目”选择“设备维修管理系统”,公共接口为“createWorkOrder”,即“生成工单”脚本“createWorkOrder”对应的公共接口,单击“下一步”,再单击“确定”。 单击页面上方的,保存设置。 拖拽页面框架组件(“基本信息”、“设备信息”、“其他信息”以及“按钮”区域)。 单击页面底部的“设计视图”页签,切换到“设计视图”。 从基本组件列表区拖拽“容器”到右侧“页面内容”中,然后再拖拽一个“表单”到“容器”中,并在“元数据表单配置向导”弹窗中,单击“取消”。 拖拽一个“容器”到“表单”下方(表单之外),作为按钮区域的容器。 图6 拖拽按钮区域容器 选择“表单”,拖一个“折叠面板”组件到“表单”中,并在页面右下角的组件树中,删除2个“折叠页”(在组件树中,选中后单击鼠标右键,再单击“删除”即可),删除后折叠面板包含1个折叠页。 图7 组件层级关系及删除多余折叠页 在“折叠面板”中,选中“折叠页签标题”,然后在右侧“属性”页签中进行以下设置: 在“样式”下的“背景”,将背景颜色修改为浅蓝色(#9BCCEF)。 图8 设置背景为浅蓝色 选中图标,设置图标颜色为深蓝色(#004080)。 图9 设置图标颜色为深蓝色 选中图标后的“标签”,设置“文本内容”为“基本信息”。 图10 设置标签内容为基本信息 您还可以根据需要,修改边距等其他样式,使其更美观。 展开组件树,将鼠标放在折叠面板上,单击右键选择“复制”,再单击右键选择2次“粘贴”,在折叠面板之后,添加2个同样的折叠面板。 图11 粘贴后的折叠面板 分别设置第二、第三个折叠面板的“折叠页签标题”为“设备信息”、“其他信息”。 图12 修改折叠页标题 单击界面上方的,保存页面。 组装“基本信息”区域。 在“基本信息”所在的折叠面板下,从左侧组件列表中,拖一个“表单”到“折叠页签内容”中,然后在“元数据表单配置向导”弹窗中,单击“取消”。 图13 拖入表单 选中“表单”,在右侧属性中,单击,在模型选择弹窗中选中“basicInfo”,单击“确定”,并在提示弹窗中,单击“绑定并生成表单”。 图14 表单数据绑定 在生成的表单中,删除如表4中的多余字段所在组件以及按钮。 表4 需要删除的组件名及组件 字段名 组件 HW__faultPhenomenon__CST 输入框 HW__customer__CST 输入框 HW__recoveryTime__CST 日期选择框 HW__arriveTime__CST 日期选择框 保存、重置 按钮 分别选择表单中的2个“分栏”,在“行布局”中单击,修改分栏为4列,并按图16所示调整字段组件的位置(选中组件,用鼠标即可拖拽组件到目的栏),调整完成后,删除多余空白分栏。 图15 调整分栏为4列 图16 调整后表单 选择表单中的各个组件,依次在右侧属性面板中修改各个组件标签,详细标签名如表5所示。 表5 修改表单组件名及组件对应字段 标签名 字段名 组件类型 设备名称 HW__equipmentId__CST 下拉框 工单标题 HW__title__CST 输入框 创建时间 createdDate 日期选择框 工单类型 HW__type__CST 下拉框 优先级 HW__priority__CST 下拉框 工单来源 HW__source__CST 输入框 备注 HW__description__CST 多行输入框 选中“设备名称”下拉框,在右侧属性页签,单击“属性值绑定”的“+”,“属性”设置为“选项”,然后再单击“模型字段”的设置图标,在弹窗中勾选“equipmentList”模型,对“设备名称”下拉框进行属性绑定。 图17 添加属性值绑定 选中“工单类型”下拉框,在右侧属性页签中,设置“维修”和“保养”2个选项。 图18 添加工单类型 选中“优先级”下拉框,在右侧属性页签中,设置“高”、“中”和“低”3个选项。 图19 添加优先级 单击界面上方的,保存页面。 组装“设备信息”区。 在“设备信息”所在的“折叠面板”中,拖入一个“表单”组件到“折叠页签内容”中,并在“元数据表单配置向导”弹窗中,单击“取消”。 选择“表单”,在右侧属性中,单击,在弹窗中选中“equipmentInfo”,单击“确定”,并在提示中单击“绑定并生成表单”。 图20 表单数据绑定 删除“name”输入框、“保存”、“取消”按钮以及按钮所在“容器”。 选择“分栏”,在“行布局”中单击,修改分栏组件为4列,并删除空白分栏,调整后如图21所示。 图21 调整后表单 修改各个输入框组件的标签名,并“公共”属性下,设置“只读”。 表6 组件名及对应字段 标签名 字段名 其他属性 设备编码 HW__equipmentSN__CST 只读 设备品牌 HW__equipmentBrand__CST 只读 设备型号 HW__equipmentModel__CST 只读 地址 HW__fullAddress__CST 只读 单击页面上方的,保存页面。 组装“其他信息”区域,组装完成后如图23所示。 图22 其他信息区域组件结构 图23 其他信息区域 在“其他信息”所在的“折叠面板”中,拖1个“表单”组件到“折叠页签内容”中,然后单击“取消”元数据表单配置向导弹窗。 设置表单样式:选中“表单”组件,在“样式”下“高级设置”中,设置表单样式“:root{margin-left:50px;}”。 在“表单”中,拖入1个“折叠面板”,并删除1个折叠页,保留2个折叠页。 修改第1个折叠页“折叠页签标题”的“标签”下的“文本内容”修改为“故障记录”。 在“故障记录”的“折叠页签内容”下,拖入1个分栏组件,设置为3列,并向第1列拖入“输入框”,并修改输入框的标签为“故障现象说明”。 修改第2个折叠页“折叠页签标题”的“标签”下的“文本内容”修改为“时间记录”。 在“时间记录”的“折叠页签内容”下,拖入1个分栏组件,并设置为3列,并分别向第1列和第2列拖入1个“日期选择框”,修改“标签”为“客户要求工程师到达现场时间”、“客户要求故障恢复时间”,然后修改“类型”为“日期时间”并设置“日期格式”为“yyyy-MM-dd HH:mm:ss”,向第3列拖入一个输入框,设置“标签”为“客户接口人”。 图24 设置日期格式 选择“故障现象说明”输入框,在右侧属性页签中,单击,为输入框绑定“basicInfo”下的“HW__faultPhenomenon__CST”字段。 参考上一步,为其他组件绑定数据字段,组件名及对应字段,如表7所示。 表7 组件名及对应字段 标签名 绑定的字段名 组件类型 客户要求工程师到达现场时间 HW__arriveTime__CST 日期选择框 客户要求故障恢复时间 HW__recoveryTime__CST 日期选择框 客户接口人 HW__customer__CST 输入框 组装“按钮”区域。 选择页面最下方“容器”,设置“水平对齐方式”为“中”,并拖入2个“按钮”组件。 图25 设置容器对齐方式 修改第1个“按钮”的“显示名称”为“提交”。 修改第2个“按钮”的“显示名称”为“取消”,“类型”为“默认按钮”。 单击页面上方的,保存页面。
  • 页面组件分析 “生成工单”页面的组装过程如下: 在页面中,拖入一个容器组件。 在容器组件中,拖入一个表单组件和容器组件。 将表单组件分割为3个区域:“基本信息”、“设备信息”、“其他信息”。 将2级容器作为“按钮”区域。 组装完成后,整个页面有4个区域,如图1所示。 图1 生成工单页面 其中,“基本信息”、“设备信息”是通过数据绑定页面模型直接创建的表单,“其他信息”及“按钮”区域是手动拖入的组件,然后再进行数据绑定,页面中详细组件分布如图2所示。 图2 页面组件分析
  • 页面模型分析 页面模型负责与页面组件交互,获取生成工单需要的数据,页面模型需要先定义,然后再与页面组件进行绑定。 对于设备维修工单,需要录入的信息包括:工单基本信息、设备信息以及工单扩展信息。 打开创单页面,有如下处理逻辑: 在“基本信息”区域指定“设备名称”时,在“设备详情”区域自动显示设备信息。该能力需要开发(equipmentSelectListQuery)脚本实现。 填写完工单,单击“提交”按钮后,会创建一个工单实例。该能力通过调用BPM实现。 结合填单页面需求,以及前端组件对应关系,需要创建如下模型: 表1 模型分析 模型名称 作用 来源 详细定义 basicInfo 保存工单的基本信息,将与“基础信息”、“其他信息”区域中各个组件绑定 自定义模型 新增的字段名称请与下面字段名称保持一致,后续将绑定页面组件。包含的节点如下,这些节点与前台页面上的工单基本信息一一对应,加粗斜体部分要替换为自己账号对应的命名空间: HW__equipmentId__CST:设备ID,字段类型SingleSelect。 HW__title__CST:工单标题,字段类型Text。 createdDate:创建时间,字段类型DateTime。 HW__type__CST:工单类型,字段类型SingleSelect。 HW__priority__CST:工单优先级,字段类型SingleSelect。 HW__description__CST:工单备注说明,字段类型TextArea。 HW__faultPhenomenon__CST:故障现象说明,字段类型Text。 HW__customer__CST:客户接口人,字段类型Text。 HW__recoveryTime__CST:客户要求故障恢复时间,字段类型DateTime。 HW__source__CST:工单来源,字段类型Text。 HW__arriveTime__CST:客户要求工程师到达现场时间,字段类型DateTime。 equipmentInfo 获取设备详细信息,将与“设备信息”区域组件绑定 自定义模型 将绑定页面组件。包含的计算节点如下,这些节点与前台页面上的设备信息一一对应,加粗斜体部分要替换为自己账号对应的命名空间: name:设备名称,字段类型Text。 HW__equipmentSN__CST:设备编码,字段类型Text。 HW__equipmentBrand__CST:设备品牌,字段类型Text。 HW__equipmentModel__CST:设备型号,字段类型Text。 HW__fullAddress__CST:设备完整地址,字段类型Text。 须知: 这些节点名称需要与设备对象的字段名保持一致。 equipmentList 查询系统中的设备,设备名称下拉框的属性值绑定模型 自定义模型 与“设备名称”下拉框绑定,将从下拉框的值赋给当前下拉框值。 equipmentOptions 查询系统中的设备,设备下拉框的可选项 服务模型 与公共接口equipmentSelectListQuery关联。 setInstanceId 查询系统中的设备,设备下拉框的可选项 服务模型 与公共接口createWorkOrder关联。
  • 创建“生成工单”公共接口 在APP视图下,单击“服务”,进入公共接口创建页面。 图2 创建公共接口入口 单击“新建”,创建“生成工单”脚本“HW__createWorkOrder”的公共接口。 设置接口参数信息:操作名称为“createWorkOrder”,版本为“1.0.0”,URL为“/createWorkOrder”,“类型”选择“脚本”,“资源”为“HW__createWorkOrder”,方法为“POST”,然后单击“保存”。 图3 新建createWorkOrder接口
  • 创建“生成工单”脚本 在“我的应用”中,单击“设备维修管理系统”,进入应用。 在“WorkOrder”目录中,将鼠标放在“Script”上,单击界面上出现的“+”,在弹出菜单中选择“脚本”。 在弹窗中,选中“创建一个新脚本”,在“名称”文本框中输入“createWorkOrder”,单击“添加”。 当编辑已有脚本时,为防止编辑时多人篡改,编辑前请单击进行锁定。 在代码编辑器中插入如下脚本代码。 脚本中红色内容请替换为实际的对象名、字段名。 //本脚本用于创建工单 import * as db from 'db';//导入处理object相关的标准库 import * as context from 'context';//导入上下文相关的标准库 import * as date from 'date'; //定义入参结构,入参包含1个参数:workOrder对象,为必填字段 @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'Object', required: true, label: 'object' }) workOrderData: object; } //定义出参结构,出参包含1个参数,workOrder的记录id @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'String' }) id: string; } //使用数据对象HW__WorkOrder__CST @useObject(['HW__WorkOrder__CST']) @action.object({ type: "method" }) export class CreateWorkOrder { //定义接口类,接口的入参为ActionInput,出参为ActionOutput @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public createWorkOrder(input: ActionInput): ActionOutput { let out = new ActionOutput(); //新建出参ActionOutput类型的实例,作为返回值 let error = new Error(); //新建错误类型的实例,用于在发生错误时保存错误信息 try { let workOrderData = input.workOrderData; //将入参赋值给workOrderData变量,方便后面使用 let s = db.object('HW__WorkOrder__CST'); //获取HW__WorkOrder__CST这个Object的操作实例 let userName = context.getUserName(); workOrderData['HW__status__CST'] = '待派单'; workOrderData['HW__assignedFme__CST'] = '派单员'; workOrderData['HW__createdBy__CST'] = userName; let id = s.insert(workOrderData); if (id) { out.id = id; } else { error.name = "WOERROR"; error.message = "无法创建工单!"; throw error; } } catch (error) { console.error(error.name, error.message); context.setError(error.name, error.message); } return out; } } 单击编辑器上方,保存脚本。 测试脚本能否正常执行。 单击编辑器上方的,执行脚本。 在界面底部输入测试数据,单击测试窗口右上角执行图标。 测试报文样例如下: { "workOrderData":{ "createdDate":"2020-09-30 12:00:00", "HW__recoveryTime__CST":"2020-09-30 12:00:00", "HW__arriveTime__CST":"2020-09-30 12:00:00", "HW__title__CST":"电梯无法关门", "HW__priority__CST":"高", "HW__workOrderId__CST":"WD0000123456", "HW__instanceId__CST":"" } } 执行成功,会在“输出”页签返回查询结果。 图1 输出工单ID号 测试成功,单击编辑器上方的,启用脚本。
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 单击页面下方的“服务”,进入公共接口创建页面。 图1 创建公共接口入口 单击“新建”,进入公共接口创建页面。 图2 公共接口创建 创建“删除设备”脚本对应的“HW__deleteEquipment”的公共接口。 设置接口参数信息,设置操作名称为“deleteEquipment”,版本为“1.0.0”,URL为“/deleteEquipment”,“类型”选择“脚本”,“资源”为“HW__deleteEquipment”,方法为“DELETE”,然后单击“保存”。 如果在“资源”下拉框中,未找到需要关联的脚本或服务编排,请检查相关脚本和服务编排是否已启用。 参照上一步,创建表1中其他的公共接口,详细接口信息如表1所示。 “HW__”请修改为实际命名空间前缀。 表1 公共接口 设置操作 版本 URL 方法 类型 资源 deleteEquipment(上一步已创建) 1.0.0 /deleteEquipment DELETE 脚本 HW__deleteEquipment equipmentSelectListQuery 1.0.0 /equipmentSelectListQuery GET 脚本 HW__equipmentSelectListQuery queryEquipments 1.0.0 /queryEquipments POST 服务编排 HW__queryEquipments
  • 验证 单击脚本编辑器上方的,执行脚本。 在界面底部单击测试窗口右上角执行图标,进行测试。 如果不设置输入参数,会出现类似如下样例的测试结果(设备名称和设备id)。 { "equipList": [ { "display": "百草园B栋2单元2号", "value": "cQue000000e1qnhgtCng" } ] } 如果设置如下输入参数。 { "id":"cQue000000e1qnhgtCng" } 则脚本返回设备的详细信息,样例如下。 测试成功,单击编辑器上方的,发布脚本。
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 在“Equipment”目录中,将鼠标放在“Script”上,单击界面上出现的“+”,在弹出菜单中选择“脚本”。 选中“创建一个新脚本”,在“名称”文本框中输入“equipmentSelectListQuery”,单击“添加”。 在代码编辑器中插入如下脚本代码。 脚本中红色内容请替换为实际的对象名、字段名。 import * as context from 'context'; import * as decimal from 'decimal'; import * as db from 'db'; //使用数据库对象HW__Equipment__CST @useObject(['HW__Equipment__CST']) @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'String' }) id: string; } @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'Any', label: 'object', isCollection: true }) equipList: object[]; @action.param({ type: 'Any', label: 'object' }) equipment: object; } @action.object({ type: "method" }) export class EquipmentSelectListQuery { @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public equipmentSelectListQuery(input: ActionInput): ActionOutput { let out = new ActionOutput(); let error = new Error; try { let objAct = db.object('HW__Equipment__CST'); if (input.id) { out.equipment = objAct.query(input.id); return out; } let option = { "options": { "orderby": [ { "field": "lastModifiedDate", "order": "desc" } ], "skip": 0, "limit": 1000 } }; let equipList = objAct.queryByCondition(null, option); let selectValue = equipList.map(function (v, i, a) { return { 'value': v['id'], 'display': v['name'] } }); out.equipList = selectValue; } catch (error) { console.error(error.name, error.message); context.setError(error.name, error.message); } return out; } } 单击脚本编辑器上方的,保存脚本。
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 在“Equipment”目录中,将鼠标放在“Script”上,单击界面上出现的“+”,在弹出菜单中选择“脚本”。 选中“创建一个新脚本”,在“名称”文本框中输入“deleteEquipment”,单击“添加”。 当编辑已有脚本时,为防止编辑时多人篡改,编辑前请单击进行锁定。 在代码编辑器中插入如下脚本代码。 脚本中红色内容请替换为实际的对象名、字段名。 //本脚本用于删除设备 import * as db from 'db';//导入处理object相关的标准库 import * as context from 'context';//导入上下文相关的标准库 //定义入参结构,入参包含1个参数:Equipment对象,为必填字段 @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'String', required: true, label: 'String' }) id: string; } //定义出参结构,出参包含1个参数,Equipment的记录id @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'String' }) id: string; } //使用数据对象HW__Equipment__CST @useObject(['HW__Equipment__CST']) @action.object({ type: "method" }) export class DeleteEquipment { //定义接口类,接口的入参为ActionInput,出参为ActionOutput @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public deleteEquipment(input: ActionInput): ActionOutput { let out = new ActionOutput(); //新建出参ActionOutput类型的实例,作为返回值 let error = new Error(); //新建错误类型的实例,用于在发生错误时保存错误信息 try { let id = input.id; let s = db.object('HW__Equipment__CST'); //获取HW__Equipment__CST这个Object的操作实例 //查询条件 let condition = { "conjunction": "AND", "conditions": [{ "field": "id", "operator": "eq", "value": id }] }; let isDeleted = s.deleteByCondition(condition); if (isDeleted) { out.id = id; } else { error.name = "EQERROR"; error.message = "删除设备失败!"; throw error; } } catch (error) { console.error(error.name, error.message); error.Error(error.name, error.message); } return out; } } 单击脚本编辑器上方的,保存脚本。
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 在“Equipment”目录中,将鼠标放在“Flow”上,单击界面上出现的,在弹出菜单中选择“服务编排”。 选中“创建一个新的服务编排”,在“标签”和“名称”文本框中输入“queryEquipments”,并设置类型为“Autolaunched Flow”,单击“添加”。 系统实际创建的脚本名称为“HW__queryEquipments”,“HW__”前缀由租户命名空间namespace决定。新建创建的服务编排,默认是当前用户锁定状态,可以进行编辑保存等操作。 当编辑已有服务编排时,为防止编辑时多人篡改,编辑前请单击进行锁定。 定义服务编排用到的变量。 单击页面右侧的,再单击结构体中的“新增”,在弹出窗口中输入结构体类型名称“Equipment”,单击“保存”。 图1 创建私有结构体 单击,再单击“对象变量”后的“+”,在弹出窗口中定义私有结构体变量“equipments”,选中“是否为数组”(该变量将作为服务编排的输出参数,且因为查询结果可能是多条记录,所以要选)。单击“保存”,如图2所示。 图2 新增私有结构体变量 单击“变量”后的“+”,设置参数名称为“name”。 单击变量后的“...”,选择“设置”,修改变量的名称、类型,选择默认值“{!$GlobalConstant.EmptyString}”信息,如图4所示。 图3 新增变量 图4 设置变量 重复上一步,定义表1中的其他变量。 表1 服务编排变量说明 变量唯一标识 描述 数据类型 默认值 name(上一步已定义) 设备名称 文本 {!$GlobalConstant.EmptyString} fullAddress 完整地址 文本 {!$GlobalConstant.EmptyString} limit 分页查询的条目数 数字 {!$GlobalConstant.Null} start 分页查询开始条目 数字 {!$GlobalConstant.Null} total 查询到的总条目数 文本 不设置 在服务编排中添加并配置脚本图元。 从左侧拖拽脚本图元到画布中。 修改图元的基本信息,“标签”和“名称”都设置为“queryEquipments”。 图5 设置脚本图元基本信息 单击,指定图元对应的脚本名称 (HW__queryEquipments),并配置脚本的输入输出参数,如果下拉选项中没有目标脚本,请检查脚本是否已启用。 单击“全局上下文”,显示变量列表。在“输入参数”中,单击“新增行”,在下拉框中选择输入参数、依次拖拽变量到输入参数的“源”下。 在“输出参数”中,单击“新增行”,在下拉框中选择输出参数,并从变量和对象变量中拖拽“目标”,如图6所示。 请直接从全局上下文拖拽变量到输入输出参数下的对应位置,请勿手动输入,手动输入的值系统可能不识别。 图6 拖拽脚本的输入输出参数 定义服务编排的输入、输出参数,并保存服务编排。 在画布上,把鼠标放在起点图元图元上,从“+”拖动鼠标,在起点图元和脚本图元间增加连线;即将当前脚本设置为服务编排的起始节点。 鼠标在画布空白处点一下,单击右侧,设置服务编排的输入输出参数,如图7所示。 图7 拖拽服务编排的输入输出参数 单击服务编排界面上方的,保存服务编排。 测试服务编排能否正常执行。 单击服务编排编辑器上方的,执行服务编排。 在“输入参数”中,输入测试数据,单击“运行”。 执行成功,界面上会返回设备对象中的全部信息,样例如下: 图8 返回样例 (可选)在服务编排编辑器单击“跟踪”,可以查看到上一步的执行日志,方便定位错误。 测试成功,单击服务编排编辑器上方的,发布服务编排。
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 在“Equipment”目录中,将鼠标放在“Script”上,单击界面上出现的,在弹出菜单中选择“脚本”。 在弹窗中,选中“创建一个新脚本”,在“名称”文本框中输入“queryEquipments”,单击“添加”。 系统实际创建的脚本名称为“HW__queryEquipments”,“HW__”前缀由租户命名空间namespace决定。新建创建的脚本,默认是当前用户锁定状态,可以进行编辑保存等操作。 当编辑已有脚本时,为防止编辑时多人篡改,编辑前请单击进行锁定。 在代码编辑器中,插入如下脚本代码。 脚本中红色内容请替换为实际的对象名、字段名。 /**************************** * 本脚本用于按条件查询设备列表 * **************************/ import * as db from 'db';//导入处理object相关的标准库 import * as context from 'context';//导入上下文相关的标准库 import * as decimal from 'decimal';//导入decimal数据类型相关的标准库 //定义入参结构 @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'String' }) name: string;//设备名称,需要按设备名称查询时传入 @action.param({ type: 'String' }) fullAddress: string;//完整地址,需要按完整地址查询时传入 @action.param({ type: 'Number', min: 0 }) start: decimal.Decimal;//分页信息,表示从第几条数据开始查询 @action.param({ type: 'Number', min: 0 }) limit: decimal.Decimal;//分页信息,表示一次查询几条数据 } //定义出参结构 @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'Any', isCollection: true, label: 'object' }) equipments: object[];//设备列表 @action.param({ type: 'String' }) total: string;//总共查到几条数据 } @useObject(['HW__Equipment__CST']) //使用数据库对象HW__Equipment__CST @action.object({ type: "method" }) export class QueryEquipments { @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public queryEquipments(input: ActionInput): ActionOutput { let out = new ActionOutput(); //新建出参ActionOutput类型的实例,作为返回值 try { //获取HW__Equipment__CST这个Object的操作实例 let s = db.object('HW__Equipment__CST'); //option是db标准库queryByCondition方法的入参(选项选项),用于对查询结果排序、分组、聚合计算等 //这里构造的是按创建时间逆序返回查询结果 let option = { "options": { "orderby": [ { "field": "createdDate", "order": "desc" } ], } }; //如果有分页 if (input.start && input.limit) { let start = decimal.toNumber(input.start);//将decimal类型转换为接口需要的number类型 let limit = decimal.toNumber(input.limit); option.options['limit'] = limit; option.options['skip'] = start; } //condition是db标准库queryByCondition方法的入参(查询条件) let condition = { "conjunction": "AND", "conditions": [] }; //基本查询条件 condition.conditions.push({ "field": "id", "operator": "isnotnull", }); condition.conditions.push({ "field": "id", "operator": "ne", "value": "" }); //按设备名称查询 if (input.name && input.name != "") { condition.conditions.push({ "field": "name",//与对象中的字段名保持一致 "operator": "contains", "value": input.name }); } //按设备地址查询 if (input.fullAddress && input.fullAddress != "") { condition.conditions.push({ "field": "HW__fullAddress__CST", "operator": "contains", "value": input.fullAddress }); } //调用按条件查询HW__Equipment__CST的接口 out.equipments = s.queryByCondition(condition, option); //构造实时监控页面需要的属性字段longitude__CST、latitude__CST、fullAddress__CST和equipmentSn__CST for (let equip of out.equipments || []) { equip['longitude__CST'] = equip['HW__longitude__CST'];//与对象中的字段名保持一致 equip['latitude__CST'] = equip['HW__latitude__CST']; equip['fullAddress__CST'] = equip['HW__fullAddress__CST']; equip['equipmentSn__CST'] = equip['HW__equipmentSN__CST']; } //调用查询符合condition条件的数据总数的接口 out.total = s.count(condition) + ""; } catch (error) { console.error(error.name, error.message); context.setError(error.name, error.message); } return out; } } 单击编辑器上方的,保存脚本。 测试脚本能否正常执行。 单击编辑器上方的,执行脚本。 在界面底部,直接单击测试窗口右上角,执行脚本。 执行成功后,会在“输出”页签返回全部设备信息。 测试成功,单击编辑器上方的,启用脚本。
  • 了解服务编排 在传统的开发中程序员一般是基于代码进行开发,程序员需要学习内容较多,开发效率相对低一些,开发门槛也高。AstroZero的服务编排功能,类似于编程中一段有流程、条件处理、判断逻辑的程序。这段程序有输入参数和输出参数、可以独立成为一个对外调用的方法。同时,在程序内部,也可以调用其他的方法。 AstroZero中的服务编排是将原来基于代码编程改变为用图形化,拖拉拽的方式去编程。如图1所示,服务编排界面是图形化、模板化的,您甚至不需要任何编程经验,将左侧面板区的组件拖拽到右侧画布、做必要的配置,就可以完成服务编排的开发。 图1 服务编排界面 服务编排界面中,可以编排如下组件: 基本组件:在服务编排引用脚本或者另一个服务编排,增/改/删/查记录,以及发送邮件、发送事件等。 逻辑组件:在服务编排中实现变量赋值Assignment、循环Loop、跳出循环Break、决策Decision和等待Wait。 商业对象:将封装好的BO能力作为服务编排中的一个节点。 连接器:将短信发送、支付等第3方连接器作为当前服务编排中的一个节点。 除了图形化编排,AstroZero也支持服务编排的在线测试验证,以及问题跟踪调试,方便您及时发现并解决问题。 服务编排测试通过、发布后,既可以直接被前端页面调用,也可以作为restful接口被第三方系统调用,也可以包装成公共接口后被调用。本节中主要是将服务编排包装成一个公共接口后,供页面调用,“管理设备”功能中涉及的业务逻辑,以及服务编排与脚本关系如表1下所示,详细操作方式及说明请参见创建业务逻辑。
  • 操作步骤 在应用中,单击下方“服务”,进入公共接口创建页面。 图1 创建公共接口入口 单击“新建”,进入新建公共接口页面。 图2 公共接口创建 创建“编辑设备”脚本“HW__editEquipment”的公共接口。 设置接口参数信息,设置标签和操作名称为“editEquipment”,版本为“1.0.0”,URL为“/editEquipment”,“类型”选择“脚本”,“资源”为“HW__editEquipment”,方法为“POST”,然后单击“保存”。 如果在“资源”下拉框中,未找到需要关联的脚本,请检查相关脚本是否已启用。 图3 设置“编辑设备”脚本的公共接口参数 在应用开发页面,单击左下角的“服务”,进入公共接口页面,查看上一步中新建的自定义接口URL“/service/HW__MyApp/1.0.0/editEquipment”,后续开发页面时,会使用这个URL。 图4 查看自定义接口URL 参照上一步,创建“按ID查询设备详情”脚本“HW__queryEquipmentDetail”的公共接口,详细接口信息如图5所示。 标签和操作名称为“queryEquipmentDetail”,版本为“1.0.0”,URL为“/queryEquipmentDetail”,“类型”选择“脚本”,“资源”为“HW__queryEquipmentDetail”,“方法”为“GET”。 图5 “HW__queryEquipmentDetail”的公共接口参数
  • 操作步骤 进入创建“设备维修管理系统”应用中创建的应用。 在“Equipment”中,将鼠标放在“Script”目录上,单击界面上出现的“+”,选择“脚本”。 在弹窗中,选中“创建一个新脚本”,在“名称”文本框中输入“queryEquipmentDetail”,单击“添加”。 系统实际创建的脚本名称为“HW__queryEquipmentDetail”,“HW__”前缀由租户命名空间namespace决定。新建创建的脚本,默认是当前用户锁定状态,可以进行编辑保存等操作。 当编辑已有脚本时,为防止编辑时多人篡改,编辑前请单击进行锁定。 在代码编辑器中插入如下脚本代码。 脚本中红色内容请替换为实际的对象名、字段名。 /***************************** * 本脚本用于按设备ID查询设备详情 * ***************************/ import * as db from 'db';//导入处理object相关的标准库 import * as context from 'context';//导入上下文相关的标准库 //定义入参结构 @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'String', required: true }) equipmentId: string;//设备ID } //定义出参结构 @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'Any', label: 'equipment' }) equipment: object;//设备对象 } @useObject(['HW__Equipment__CST'])//使用数据库对象HW__Equipment__CST @action.object({ type: "method" }) export class QueryEquipmentDetail { @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public queryEquipmentDetail(input: ActionInput): ActionOutput { let out = new ActionOutput(); //新建出参ActionOutput类型的实例,作为返回值 let error = new Error(); //新建错误类型的实例,用于在发生错误时保存错误信息 try { //必填校验 if (!input.equipmentId || input.equipmentId == "") { error.name = "EQM"; error.message = "Equipment id is required."; throw error; } //获取HW__Equipment__CST这个Object的操作实例 let s = db.object('HW__Equipment__CST'); //查询字段(全部) let option = {}; //查询条件 let condition = { "conjunction": "AND", "conditions": [{ "field": "id", "operator": "eq", "value": input.equipmentId }] }; //调用按条件查询Equipment__CST的接口 let record = s.queryByCondition(condition, option); //如果查询到数据 if (record && record[0]) { //拼接前台省市区级联选择器的数据模型 let cascaderAddress = []; if (record[0].HW__installationSiteProvince__CST) { cascaderAddress.push(record[0].HW__installationSiteProvince__CST); if (record[0].HW__installationSiteCity__CST) { cascaderAddress.push(record[0].HW__installationSiteCity__CST); if (record[0].HW__installationSiteArea__CST) { cascaderAddress.push(record[0].HW__installationSiteArea__CST); } } } record[0].cascaderAddress = cascaderAddress; //将结果挂入输出对象中 out.equipment = record[0] } } catch (error) { console.error(error.name, error.message); context.setError(error.name, error.message); } return out; } } 单击编辑器上方的,保存脚本。
  • 验证并发布 测试新增逻辑能否正常执行。 单击编辑器上方的,执行脚本。 在界面底部输入测试数据,单击测试窗口右上角执行图标。 测试报文样例如下,equipmentId可参考创建“编辑设备”脚本验证新增设备时生成的设备ID: { "equipmentId": "cQue000000e1qnhgtCng" } 执行成功,会在“输出”页签返回查询结果,返回结果是上一节中新增的设备信息。 图1 查询返回的设备信息 测试成功,单击编辑器上方的,启用脚本。
  • 公共接口 公共接口是对脚本、服务编排和对象进行再包装的一种方式。将创建的脚本、服务编排、对象包装成一个新公共服务,可以使得接口的URL地址的表达形式更规范,方便让前端页面或第三方系统进行调用。 因此,在创建完后台逻辑后(服务编排、脚本、对象),就需要先将此接口包装成标准的公共接口,才能被调用。本章节中创建了2个业务脚本,因此需要对应创建2个公共接口,供前端页面调用。 创建公共接口的入口:在APP视图下,单击下方“服务”,即可进入公共接口创建页面。 图1 创建公共接口入口 图2 公共接口基本信息 图3 公共接口URL 父主题: 背景和原理
  • 样例代码解读 通过下面详细的脚本代码内容解读,使您对脚本有一个更具体的认识。 一般情况下,编写脚本的大致流程为: 按需引入平台标准库。 图2 引入平台标准库 定义出参、入参结构。 图3 定义入参 图4 定义出参 定义方法以及使用的对象。 图5 定义方法及使用对象 进行数据库操作。 图6 数据库相关操作 下面通过解读以下脚本样例,了解一个脚本的总体结构框架、编写要求。 import * as decimal from 'decimal'; @action.object({type: "param"}) export class ActionInput { @action.param({type: 'String', required: true, label: 'your name', description: 'please input your name'}) name: string; @action.param({type: 'Number', required: true, min: 1, max: 100, message: 'age must during [1, 100]'}) age: decimal.Decimal; @action.param({type: 'Date', pattern: 'yyyy-MM-dd'}) birthday: Date; @action.param({type: 'String', isCollection: true}) schools: string[]; @action.param({type: 'Boolean'}) married: boolean; @action.param({type: 'MyObject'}) obj: MyObject; } @action.object({type: "param"}) export class MyObject { @action.param({type: 'String'}) something: string; @action.param({type: 'Number'}) otherthing: decimal.Decimal; } @action.object({type: "param"}) export class ActionOutput { @action.param({type: 'String', isCollection: true}) greets: string[]; } @action.object({type: "method"}) export class ActionDemo { @action.method({ label: 'greeting something', description: 'greeting something.', input: 'ActionInput', output: 'ActionOutput' }) public greet(inarg: ActionInput): ActionOutput { console.log('name = ', inarg.name); console.log('age = ', inarg.age); console.log('birthday = ', inarg.birthday); console.log('schools = ', inarg.schools); console.log('married = ', inarg.married); console.log('obj = ', inarg.obj); let out = new ActionOutput(); out.greets = ['hello', 'hi', 'how are you', 'how old are you', 'long time no see']; return out; } } 上述示例脚本包括三部分内容: 导入标准库或其他模块。 示例中第1行,表示将使用平台提供的decimal库。 import * as decimal from 'decimal'; 除了平台预置标准库,还可以声明对其他自定义模块的引用。例如,已经提前开发了一个脚本circle,可以用如下方式加载。 import * as circle from './circle'; 定义输入、输出变量。 脚本可以有多个输入、输出参数,也可以没有。所有的输入或输出参数必须封装在一个class中,作为实例成员。 本例中,脚本有6个输入参数,被封装为ActionInput。每个参数都必须定义其参数类型,同时还可以定义是否必填、标签、最大值、最小值等可选属性。 @action.object({type: "param"}) export class ActionInput { @action.param({type: 'String', required: true, label: 'your name', description: 'please input your name'}) name: string; @action.param({type: 'Number', required: true, min: 1, max: 100, message: 'age must during [1, 100]'}) age: decimal.Decimal; @action.param({type: 'Date', pattern: 'yyyy-MM-dd'}) birthday: Date; @action.param({type: 'String', isCollection: true}) schools: string[]; @action.param({type: 'Boolean'}) married: boolean; @action.param({type: 'MyObject'}) obj: MyObject; } 因为第6个输入参数“obj”的参数类型为自定义对象,所以还需要给出“MyObject”的定义。 @action.object({type: "param"}) export class MyObject { @action.param({type: 'String'}) something: string; @action.param({type: 'Number'}) otherthing: decimal.Decimal; } 脚本有1个输出参数,被封装为ActionOutput。 @action.object({type: "param"}) export class ActionOutput { @action.param({type: 'String', isCollection: true}) greets: string[]; } 定义方法。 样例中,ActionDemo是外部调用的class,使用export导出。ActionDemo定义了一个action method,使用action.method装饰,表明调用脚本时从此方法入口。greet是class的实例方法,其输入、输出参数就是前面定义的ActionInput和ActionOutput。 在一个脚本文件里面,action.method只能使用一次。 @action.object({type: "method"}) export class ActionDemo { @action.method({ label: 'greeting something', description: 'greeting something.', input: 'ActionInput', output: 'ActionOutput' }) public greet(inarg: ActionInput): ActionOutput { console.log('name = ', inarg.name); console.log('age = ', inarg.age); console.log('birthday = ', inarg.birthday); console.log('schools = ', inarg.schools); console.log('married = ', inarg.married); console.log('obj = ', inarg.obj); let out = new ActionOutput(); out.greets = ['hello', 'hi', 'how are you', 'how old are you', 'long time no see']; return out; } } 脚本编辑页面不支持单步调试,样例里的console.log可实现在日志里打印过程输出,方便代码调试。
  • 了解应用目录及菜单 一个业务系统通常包括前端页面、后台逻辑和数据库表。因此,AstroZero采用类似的结构管理应用程序。 如图1所示,应用管理页面包含三部分(红框1、红框2和红框3): 红框1中是当前应用的页面、模型和逻辑。在后续章节中,开发的页面、对象及后台逻辑,推荐按以下规划的方式,将应用资源分别放在对应的目录下: Object:数据对象 Script:脚本 Flow:服务编排 Bpm:BPM Page:前端页面 红框2中是应用管理功能,例如预览应用、编译打包、发布应用等。 红框3中是应用设置功能,例如设置应用导航、页面设置等。 红框4中是AstroZero应用开发环境的导航菜单,单击“首页”可返回开发环境首页。 图1 应用的管理目录 父主题: 创建应用
  • 背景信息 工作队列是在业务场景中,用来记录可以受理相同具体业务的用户群体。 这种记录一直保留在队列中,直到用户接受它们并进行处理,或它们被转移到另一个队列。您可以指定每个队列支持的对象集合,以及允许从队列检索记录的用户组(用户、业务用户等)。 创建工作队列主要包含两方面内容: 添加队列的成员。 队列成员可以是单个用户、公共组、单个角色或带有下级角色的角色,以及业务用户;如果队列的成员是角色,此队列将包含角色中所有的用户。 配置队列支持的对象。 配置了支持的对象后,涉及特定数据对象的触发器、待审批任务才能进入该队列。
  • 入门实践 当您购买了Astro轻应用实例后,可以根据业务需要搭建低代码、零代码和大屏应用。本文介绍Astro轻应用常见的搭建实践,帮助您更好的使用Astro轻应用。 表1 常用最佳实践 实践 描述 通过AstroZero开发设备维修管理应用 本最佳实践以IoT领域电梯设备运维管理和维修的应用场景为主线,由浅入深的向您介绍如何在AstroZero中开发该应用。 使用AstroZero将客户与订单数据关联并同步修改 本最佳实践主要向您介绍如何将两个对象进行关联,实现对象数据的同步修改功能。 通过AstroZero中的脚本实现表格数据的增加和删除 本最佳实践向您介绍如何通过脚本,实现表格数据的增加和删除。 通过AstroZero流程模板创建出差审批应用 本最佳实践通过创建一个出差审批应用,帮助您快速熟悉AstroZero中的工作流。 为AstroZero调查问卷应用新增调查项 本最佳实践主要向您介绍如何通过对象模型,为调查问卷应用新增调查项。 为AstroZero标准页面中的表格增加求和等计算能力 本最佳实践主要向您介绍如何为标准页面中的表格添加计算能力。 在AstroZero高级页面中使用花瓣图展示订单数据 本最佳实践主要向您介绍如何在高级页面中,通过玫瑰花饼图展示订单数据。 通过AstroZero中的连接器上传并识别身份证图片 本最佳实践主要向您介绍如何通过OCR连接器,实现身份证信息的识别和存储能力。 将AstroZero中的应用发布成 WeLink 轻应用 本最佳实践以Astro轻应用调查问卷轻应用为例,向您介绍如何把AstroZero上开发的应用发布成WeLink(蓝标)轻应用。
  • 自定义 域名 访问介绍与配置 当以自定义域名访问OBS桶时,需要先将该自定义域名同对应OBS桶访问域名进行绑定,相关配置请参见自定义域名绑定简介,自定义域名绑定配置。 当在自定义域名上配置了 CDN加速 服务,即自定义域名为CDN服务的加速域名时,需要额外对CDN服务进行配置,以保证可以正常使用自定义域名访问OBS服务。 以华为云CDN服务为例,相关配置如下所示: 登录华为云CDN服务,从CDN服务左侧列表中选择域名管理项,在该项中可以查看到所有配置的CDN服务域名信息。 配置源站。单击要使用的自定义域名项,进入域名配置界面,编辑源站配置,选择主源站类型为源站域名类型,对应源站为要访问的OBS桶域名。 配置回源HOST。回源HOST必须指定为加速域名即访问OBS服务时访问的自定义域名,否则可能会出现回源鉴权失败的问题。
  • 代理设置失效 1、sdk Windows端 demo中设置代理时出现如下问题,程序报错且代理设置失败 问题根因:某些sdk版本demo头文件eSDKOBS.h与sdk的eSDKOBS.h未同步更新,导致option中设置的代理失效 解决方法:将yourSDKpath\source\eSDK_OBS_API\eSDK_OBS_API_C++\inc\eSDKOBS.h 替换掉‪yourSDKpath\source\eSDK_OBS_API\eSDK_OBS_API_C++\build\obs\demo\eSDKOBS.h 同时demo做如下改动来适配eSDKOBS.h的更改(适配过程以3.22.7版本为例,其他版本可能略有不同) 在文件yourSDKpath\source\eSDK_OBS_API\eSDK_OBS_API_C++\build\obs\demo\ demo_windows.cpp中4749行新增obs_upload_file_server_callback server_callback; 同时4750行中,函数upload_file第四个参数后增加, server_callback,如下图 2、设置了代理还是连接失败,可能是因为sdk的 request.c的 get_api_version函数中未设置代理 可以参考sdk的 request.c的 setup_curl函数中设置代理的方式在get_api_version函数中添加向curl中设置代理(CURLOPT_PROXY项与CURLOPT_PROXYUSERPWD项)的逻辑进行修复 父主题: 常见问题
  • 常见编译问题 本章节收录了编译sdk或者sdk demo可能遇到的一些编译问题,对应版本的问题可能在其他旧版本中也出现,都可以参考 v3.23.3版本反映的常见问题: 问题1: 编译sdk的vs工程报错: 报错文件:目录${yourSDKPath}\platform\eSDK_LogAPI_V2.1.10\C\include下面的eSDKLogAPI.h、eSDKLogDataType.h这两个文件 vs编译器错误码:c2018 解决方案: 修改上述目录下的两个文件(eSDKLogAPI.h、eSDKLogDataType.h)的行尾序列为CRLF 问题2:sdk的vs工程编译成功后还需要手动拷贝lib、dll到demo工程目录下才能运行demo程序,不够方便 解决方案(以Debug,x64为例): 1、编译Debug,x64的obs.sln解决方案 2、打开obs_demo.sln解决方案,调整属性为Debug,x64,按图操作后,填入值: PATH=%PATH%;$(ProjectDir)..\..\eSDK_OBS_API_C++\build\vc100\Debug;$(ProjectDir)..\..\eSDK_OBS_API_C++\bin\win64_x64_msvc\release;$(ProjectDir)..\..\..\..\platform\eSDK_LogAPI_V2.1.10\C\release_x64;$(LocalDebuggerEnvironment) v3.22.7版本反映的Sdk本体常见编译问题 问题1: 解决方案:通过下面的脚本去编译securec组件,并将产物拷贝到对应目录 export Your_SDK_path='Your_SDK_path' cd ${Your_SDK_path}/platform/huaweisecurec/src/ make mkdir ${Your_SDK_path}/platform/huaweisecurec/lib/linux cp ${Your_SDK_path}/platform/huaweisecurec/lib/libsecurec.so ${Your_SDK_path}/platform/huaweisecurec/lib/linux cd ${Your_SDK_path}/source/eSDK_OBS_API/eSDK_OBS_API_C++ #需要先cd到目录下,因为脚本按相对路径查找依赖项 sh build.sh 问题2: 解决方案: 在source\eSDK_OBS_API\eSDK_OBS_API_C++\src\object\download_file.c 中删除26、27行(如下) pthread_mutex_t g_mutexThreadCheckpoint; pthread_mutex_t g_mutexThreadCheckpoint_download; 在source\eSDK_OBS_API\eSDK_OBS_API_C++\src\object\object_common.c 中删除31、32行(如下) pthread_mutex_t g_mutexThreadCheckpoint; pthread_mutex_t g_mutexThreadCheckpoint_download; 之后编译即可 问题3: 这个问题一般是在其他路径中执行build.sh导致的,需要先cd到对应目录下再执行,因为脚本按相对路径查找依赖项,执行如下脚本编译 export Your_SDK_path='Your_SDK_path' cd ${Your_SDK_path}/source/eSDK_OBS_API/eSDK_OBS_API_C++ sh build.sh v3.22.7版本反映的常见Sdk Demo编译问题 问题1: 需要拷贝cjson头文件以及相关库(如果是arm需要把路径中的linux替换为arm) 同时需要改Makefile export Your_SDK_path='Your_SDK_path' export Your_DEMO_path='Your_DEMO_path' cp ${Your_SDK_path}/build/script/Provider/build/linux/cjson-1.7.15/include/cJSON.h ${Your_DEMO_path}/include cp ${Your_SDK_path}/build/script/Provider/build/linux/cjson-1.7.15/lib/libcjson.so* ${Your_DEMO_path}/lib 打开${Your_DEMO_path}/demo/Makefile 将16行(LIB=-leSDKOBS -lsecurec)替换为LIB=-lcjson -leSDKOBS -lsecurec cd ${Your_DEMO_path}/demo make 父主题: 常见问题
  • 设置方式 修改lib目录下的OBS.ini,配置日志的大小、个数以及级别(其中*_Run参数的配置为最常用的配置项): ;Every line must be less than 1024 [LogConfig] ;Log Size: unit=KB, 10MB = 10KB * 1024 = 10240KB LogSize_Interface=10240 LogSize_Operation=10240 LogSize_Run=10240 ;Log Num LogNum_Interface=10 LogNum_Operation=10 LogNum_Run=10 ;Log level: debug = 0,info = 1,warn = 2,error = 3 LogLevel_Interface=0 LogLevel_Operation=0 LogLevel_Run=0 ;LogFilePermission LogFilePermission=0600 [ProductConfig] ;Product Name sdkname=eSDK-OBS-API-Linux-C [LogPath] ;Log Path is relative to the path of configuration file LogPath=../logs
  • 其他日志相关配置 Windows下,OBS.ini中LogPath字段可以以wchar_t格式读取,需要通过设置文件路径编码来实现,案例如下: set_file_path_code(UNICODE_CODE);//默认是ANSI_CODE 设置后,以下方法的本地文件路径也需要是wchar_t类型(参数是以char*格式传入,内部处理逻辑是wchar_t) 表1 影响函数 说明 download_file 参数download_file_config的downLoad_file、check_point_file成员需要是wchar_t类型,以char*格式传入 upload_file 参数upload_file_config的upload_file、check_point_file成员需要是wchar_t类型,以char*格式传入 set_obs_log_path 参数log_path需要是wchar_t类型,以char*格式传入
  • 日志级别 当系统出现问题需要定位且当前的日志无法满足要求时,可以通过修改日志的级别来获取更多的信息。其中DEBUG(0)日志信息最丰富,ERROR(3)日志信息最少。 具体说明如下: DEBUG(0):调试级别,如果设置为这个级别,除了打印INFO级别的信息外,还将打印其它帮助调试的信息等。 INFO(1):信息级别,如果设置为这个级别,除了打印WARN级别的信息外,还将打印OBS接口的调用过程和关键信息等。 WARN(2):告警级别,如果设置为这个级别,除了打印ERROR级别的信息外,还将打印一些关键事件的信息,如curl_global_init初始化失败等。 ERROR(3):错误级别,如果设置为这个级别,仅打印发生异常时的错误信息。
  • 参数说明 加解密参数server_side_encryption_params说明如下表所示: 字段名 类型 说明 encryption_type obs_encryption_type 服务端加密方式 OBS_ENCRYPTION_KMS:使用SE-KMS加密方式 OBS_ENCRYPTION_SSEC:SSE-C加密使用 kms_server_side_encryption char * 使用该参数表示服务端加密是SSE-KMS方式。目标对象使用SSE-KMS方式加密。 kms_key_id char * SSE-KMS方式下使用该参数,表示加密目标对象使用的主密钥,如果用户没有提供该头域,那么默认的主密钥将会被使用。 ssec_customer_algorithm char * SSE-C方式下使用该参数,表示加密目标对象使用的算法。 ssec_customer_key char * SSE-C方式下使用该参数,表示加密目标对象使用的密钥。 des_ssec_customer_algorithm char * SSE-C方式下使用该参数,表示解密源对象使用的算法。 des_ssec_customer_key char * SSE-C方式下使用该参数,表示解密源对象使用的密钥。用于解密源对象。
  • 静态网站托管简介 开发过程中,您有任何问题可以在github上提交issue,或者在华为云 对象存储服务 论坛中发帖求助。 您可以将静态网站文件上传至OBS的桶中作为对象,并对这些对象赋予公共读权限,然后将该桶配置成静态网站托管模式,以实现在OBS上托管静态网站的目的。第三方用户在访问您网站的时候,实际上是在访问OBS的桶中的对象。在使用静态网站托管功能时,OBS还支持配置请求重定向,通过重定向配置您可以将特定的请求或所有请求实施重定向。 更多关于静态网站托管的内容请参考静态网站托管。 父主题: 静态网站托管
共100000条