using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
[System.ComponentModel.Description(\)] publicclassClass8 : AbstractBillPlugIn {
publicoverridevoid BarItemClick(BarItemClickEventArgs e) {
if (e.BarItemKey == \) {
this.View.Model.SetValue(\, 10); //调用乘数字段的值更新服务
//由于乘数字段在单据头,这里的行号传0
this.View.InvokeFieldUpdateService(\, 0); } } } }
2.4. 在动态表单插件中,如何修改界面数据 2.4.1. 如何新增单据体行
? 实现思路
? 调用Model的CreateNewEntryRow方法 ? CreateNewEntryRow介绍
? Model提供了5个重载方法,分别介绍
? publicvoid CreateNewEntryRow(DynamicObject parentRow, SubEntryEntity
entity, int row)
在父单据体对应的子单据体上新增一行 名称 parentRow entity row 类型 DynamicObject SubEntryEntity int 说明 父单据体行实体数据包 子单据体实体元数据描述信息 新创建的子单据体行,在此父分录对应的子单据体中对应的是哪一行,如果传-1,默认新增在子单据体的最后一行 ? publicvoid CreateNewEntryRow(Entity entity)
在指定单据体的最后一行,新增一行分录 名称 entity ? publicvoid CreateNewEntryRow(Entity entity, int row)
在指定单据体的指定行,新增一行分录 名称 entity 类型 Entity 说明 指定需要创建一行分录的单据体的元数据描述信息 类型 Entity int 说明 指定新增行的单据体的元数据描述信息 指定新增的单据体行是当前单据体的第几行 row ? publicvirtualvoid CreateNewEntryRow(Entity entity, int row, DynamicObject
rowDataEntity)
在指定单据体的指定行,新增一行分录 名称 entity row rowDataEntity 类型 Entity int DynamicObject 说明 指定新增行的单据体的元数据描述信息 新增到哪一行 待新增行的单据体实体数据包 ? publicvoid CreateNewEntryRow(string key)
在指定单据体唯一标示的单据体上,新增一行分录,默认新增到最后一行 名称 key
? 示例代码 C#
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata.EntityElement; using Kingdee.BOS.Orm.DataEntity; using System;
using System.Collections.Generic;
类型 string 说明 待新增单据体行的单据体唯一标示
using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
publicclassClass9 : AbstractBillPlugIn {
publicoverridevoid ButtonClick(ButtonClickEventArgs e) {
//entity:单据体唯一标识 //subentity:子单据体唯一标识 //获取单据体元数据描述
Entity entity = this.View.BusinessInfo.GetEntity(\); //获取子单据体元数据描述
SubEntryEntity subentity = this.View.BusinessInfo.GetEntity(\) asSubEntryEntity; //为单据体新增一行分录
this.View.Model.CreateNewEntryRow(\); this.View.Model.CreateNewEntryRow(entity, -1); this.View.Model.CreateNewEntryRow( entity, -1,
this.View.Model.DataObject[\] asDynamicObject); //为子单据体新增一行
this.View.Model.CreateNewEntryRow(
this.View.Model.DataObject[\] asDynamicObject, subentity, -1); } } }
2.4.2. 如何删除单据体行
? 实现思路
? 调用model的DeleteEntryRow方法 ? DeleteEntryRow介绍
? 传递待删除行的单据体唯一标示和要删除行的行号 ? 示例代码 C# using Kingdee.BOS.Core.Bill.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
publicclassClass10 : AbstractBillPlugIn {
publicoverridevoid ButtonClick(ButtonClickEventArgs e) {
//entity:单据体唯一标识 //删除单据体第一行分录
this.View.Model.DeleteEntryRow(\, 1); } } }
2.4.3. 如何给普通字段赋值
普通字段,在单据的数据包中,只是用一个属性(DynamicProperty)存储,赋值比较简单: ? 赋值方法列举
? 调用model的SetValue方法 ? 使用字段元数据的动态属性赋值 ? 直接为DynamicObject对象属性赋值 ? 示例代码 C#
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata.FieldElement; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
[System.ComponentModel.Description(\)] publicclassClass11 : AbstractBillPlugIn {
publicoverridevoid ButtonClick(ButtonClickEventArgs e) {
//为数量字段赋值10,数量字段的唯一标示是FQty,其动态绑定属性是Qty
//调用SetValue赋值(推荐)
this.View.Model.SetValue(\, 10);
//调用动态实体属性赋值(仅供参考)
Field field = this.View.BusinessInfo.GetField(\);
field.DynamicProperty.SetValue(this.View.Model.DataObject, 10);
//使用动态实体数据属性,直接赋值(仅供参考,极不推荐) this.View.Model.DataObject[\] = 10; } } }
? 特别说明
? 不同字段类型,赋值方法、接受的值类型有差别
? 使用字段元数据的动态属性赋值与直接使用数据模型的属性赋值,其效果是一样的,
这种赋值方式直接修改模型数据包数据,不触发字段的值改变事件,极不推荐; ? 使用this.View.Model.SetValue方法赋值,除了修改数据包数据,还触发一系列插件
事件,如beforeupdatevalue,datachanged,触发实体服务规则等,推荐使用;
2.4.4. 如何给基础资料字段赋值
基础资料字段,在单据数据包中,会有两个属性(分别为DynamicProperty, RefIDDynamicProperty)存储,直接操作数据包比较复杂。另外,基础资料值是一个DynamicObject类型,获取基础资料值也有些复杂。 ? 实现思路
? 使用基础资料id值,调用Model的SetValue方法
? 使用基础资料完整数据包,调用Model的SetValue方法 ? 使用动态属性赋值
? 使用DynamicObject直接访问属性赋值 ? 示例代码 C#
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.FieldElement; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.ServiceHelper; using System;
K/3 Cloud BOS 插件开发百问百答
修订记录 Ver. No V1.0 日期 20150428 编制\\修订 张晋博 校对 丁振华 批准 赖碧云 修改的章节号 初始版本,共39个问题 问题和意见 如果你对文档有任何意见、问题或想法,或者你的问题未在此文档中找到答案,请通过电子邮件联系我们
jinbo_zhang@kingdee.com
目录
K/3 Cloud BOS 插件开发百问百答 ................................................................................................. 1 1. 入门篇....................................................................................................................................... 4
1.1. 如何创建并启用各类插件 ....................................................................................... 4
1.1.1. 如何创建并启用动态表单插件 ....................................................................... 4 1.1.2. 如何创建并启用单据编辑插件 ....................................................................... 8 1.1.3. 如何创建并启用基础资料编辑插件 ............................................................... 9 1.1.4. 如何创建并启用列表插件 ............................................................................. 10 1.1.5. 如何创建并启用操作插件 ............................................................................. 11 1.1.6. 如何创建并启用账表取数插件 ..................................................................... 15 1.1.7. 如何创建并启用单据转换插件 ..................................................................... 18 1.1.8. 如何创建并启用反写插件 ............................................................................. 18 1.2. 为何插件不起作用,如何排查 ............................................................................. 20 2. 进阶篇..................................................................................................................................... 21
2.1. 插件代码,如何自行调用单据操作服务 ............................................................. 21
2.1.1. 如何加载(Load)单据 ....................................................................................... 21 2.1.2. 如何调用保存(Save)操作 ............................................................................... 25 2.1.3. 如何调用提交(Submit)操作 ........................................................................... 28 2.1.4. 如何调用审核/反审核(Audit/UnAudit)操作 ................................................. 31 2.1.5. 如何调用禁用(Disabled)操作 ........................................................................ 34 2.1.6. 如何删除(Delete)单据 .................................................................................... 37 2.2. 调用单据操作后,如何判断结果,并处理交互提示 ......................................... 40 2.3. 插件给字段赋值后,为什么不执行字段”值更新属性”上配置的表单服务 ...... 44 2.4. 在动态表单插件中,如何修改界面数据 ............................................................. 46
2.4.1. 如何新增单据体行 ......................................................................................... 46 2.4.2. 如何删除单据体行 ......................................................................................... 48 2.4.3. 如何给普通字段赋值 ..................................................................................... 49 2.4.4. 如何给基础资料字段赋值 ............................................................................. 50 2.4.5. 如何动态设置下拉列表字段的可选项 ......................................................... 52 2.5. 字段标识(Key)、字段名(FieldName)、属性名(PropertyName)的差别 ............... 53 2.6. 在动态表单中,如何实现文件下载 ..................................................................... 53 2.7. 如何支持用户把本地文件上传到服务器 ............................................................. 57 2.8. 以实例说明如何为动态表单取数、填充 ............................................................. 58 2.9. 如何为预置账表,添加字段 ................................................................................. 60 2.10. 如何获取基础资料的属性值 ................................................................................. 60 2.11. 保存前,如何为新建的单据数据包、单据体行,填写主键 ............................. 61 2.12. 在动态表单插件中,如何显示指定界面 ............................................................. 62 2.13. 如何为收款单,往来单位类型,添加新的基础资料 ......................................... 64 2.14. 如何创建、调试自定义执行计划 ......................................................................... 66 2.15. 如何通过按钮实现F8选择返回效果 ................................................................... 67 2.16. 如何在操作插件中,自定义操作校验器并启用 ................................................. 69 2.17. 如何实现超链接,打开外部URL地址 ................................................................ 73 2.18. 如何获取基础资料字段的类别(FormId) ............................................................... 74
3.
高级篇..................................................................................................................................... 75 3.1. 如何给单据体表格,增加自定义过滤行 ............................................................. 75
1. 入门篇
1.1. 如何创建并启用各类插件 1.1.1. 如何创建并启用动态表单插件
创建插件工程
? 动态表单插件,运行在K/3 Cloud的Web服务层,需要建立一个独立的工程管理动态表
单插件类;
? 动态表单插件工程,建议命名格式为[开发商][.K3][.业务领域][.子系统].Business.PlugIn;
如JD.K3.SCM.PUR.Business.PlugIn;
? 创建工程过程:Visual Studio → New → Project
? Visual C# → Class Library →选择工程文件存放位置→ OK
? 工程References右键,添加工程引用,所添加组件都来自Cloud网站的website\\bin路
径
? 修改插件工程输出路径为Cloud网站路径website\\bin:选中插件工程→右键→ Property
(属性)→ Build页签→ Output Path(输出路径)
// 默认值是false 是否支持移动审批交互处理,移动端目前仅能支持到是否的交互处理。如果是简单的是/否交互处理,可以把这个值设置为true publicbool SupportMobile { get; set; } }
? 如何判断是否存在交互提示:
? 操作返回结果如果其交互上下文不为null,说明需要进行交互 ? 交互实现基本信息包含在交互信息上下文中
? 如何判断是否存在校验错误或警告信息
? 如果返回结果中的IsSuccess为false,说明执行当前操作失败,分析操作返回结果
的ValidationErrors是否不为空,包含校验错误信息
? 示例代码 C#
using Kingdee.BOS.Core.Bill.PlugIn; using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Interaction; using Kingdee.BOS.Core.Metadata; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.ServiceHelper; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
publicclassClass14 : AbstractBillPlugIn {
publicoverridevoid ButtonClick(ButtonClickEventArgs e) {
//保存id为10001的其他出库单 IOperationResult result = newOperationResult();
//获取其他出库单元数据 FormMetadata metadata =
MetaDataServiceHelper.Load(this.Context,\) asFormMetadata; //加载id为10001的其他出库单 DynamicObject[] objs =
BusinessDataServiceHelper.Load(
this.Context, newobject[]{10001},
metadata.BusinessInfo.GetDynamicObjectType());
//调用保存操作,用result临时变量持有操作返回结果对象 result =
BusinessDataServiceHelper.Save(this.Context, metadata.BusinessInfo, objs);
//分析操作结果
if (result.InteractionContext != null) {
if (!string.IsNullOrWhiteSpace(result.InteractionContext.InteractionFormId)) {
this.DoComplextInteraction(result); return;
}
elseif (!string.IsNullOrWhiteSpace(result.InteractionContext.SimpleMessage)) {
this.DoSimpleInteraction(result); return;
} } else
{
//保存不成功,并且要求显示信息
if (!result.IsSuccess && result.IsShowMessage) {
//循环读取result.ValidationErrors信息,抛出来 } } }
privatevoid DoComplextInteraction(IOperationResult result) {
if (result.InteractionContext != null
&& result.InteractionContext.InteractionFormId.Equals(\)) {//调用K3显示器处理交互
this.View.ShowK3Displayer(result.InteractionContext.K3DisplayerModel, (o) => {
if (o != null&& (o.ReturnData isK3DisplayerModel) && (o.ReturnData asK3DisplayerModel).IsOK) {
//重新执行保存,设置Option忽略交互信息
//this.Option.SetInteractionFlag(result.InteractionContext.Option.GetInteractionFlag()); } }); } else
{//调用业务定制Form进行交互
if (result.InteractionContext.FormShowParameter == null) {
result.InteractionContext.FormShowParameter = newDynamicFormShowParameter();
result.InteractionContext.FormShowParameter.OpenStyle.ShowType = ShowType.Modal; }
result.InteractionContext.FormShowParameter.FormId = result.InteractionContext.InteractionFormId;
result.InteractionContext.FormShowParameter.ParentPageId = this.View.PageId;
this.View.ShowForm(result.InteractionContext.FormShowParameter, (o) => {
if (o != null&& (o isInteractionFormResult) && (o asInteractionFormResult).IsOK) {
//重新执行保存,设置Option忽略交互信息 } }); } }
privatevoid DoSimpleInteraction(IInteractionResult result) {
if (result == null) return;
this.View.ShowMessage(result.InteractionContext.SimpleMessage, MessageBoxOptions.YesNo, (o) => {
InteractionFormResult formResult = newInteractionFormResult(o == MessageBoxResult.Yes, o);
if (o == MessageBoxResult.Yes) {
//重新执行保存,设置Option忽略交互信息 }
},
result.FormTitle); } } }
2.3. 插件给字段赋值后,为什么不执行字段”值更新属性”上
配置的表单服务
背景分析
设计一张单据,单据头有3个整数字段,例如分别为乘数、被乘数、积,各字段BOSIDE配置关键属性如下: ? 乘数
? 缺省值:2
? 勾选及时触发值更新
? 配置字段值更新,前提条件是乘数和被乘数都不为null,积=乘数*被乘数 ? 被乘数
? 缺省值:2
设计一个菜单,点击时,插件为乘数SetValue为10,插件代码如下 C#
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
[System.ComponentModel.Description(\)] publicclassClass8 : AbstractBillPlugIn {
publicoverridevoid BarItemClick(BarItemClickEventArgs e) {
if (e.BarItemKey == \) {
this.View.Model.SetValue(\, 10); } } } }
现象描述
新增单据时,由于默认值,乘数和被乘数都是2,这时,点新增的菜单,乘数变成10,但是没有触发在乘数字段上设计的值更新事件,也就是说积的值没有变化;此时,在单据界面上修改乘数的值为3,鼠标从乘数字段移开,积变成6,也就是说,界面修改乘数的值触发了乘数字段的值更新事件
刨根问底
? 插件写SetValue为乘数字段赋值,不会触发字段值更新服务,也就是说SetValue与调
用字段值更新服务是相互解耦的两个服务,并不是紧耦合的关系,所以插件对目标字段SetValue之后,不会触发此字段上设计的字段值更新
? 在界面上修改乘数字段,由于乘数字段勾选了即时触发值更新,所以前端控件会及时触
发updatevalue方法(通过httpwatch可看出),在服务端响应updatevalue的一系列方法中,除了为此字段执行setvalue的操作,同时也调用了此字段上设计的值更新服务 坚持到底
插件在SetValue之后还是希望能够调用字段值更新服务,效果就像是在单据页面上编辑此字段,鼠标移开,完成SetValue后,调用InvokeFieldUpdateService方法 C#
submitService.Submit( this.Context,
materialMetadata.BusinessInfo, newobject[] { 10001 }, \); } } }
2.1.4. 如何调用审核/反审核(Audit/UnAudit)操作
2.1.4.1. Web层插件,如何调用审核/反审核(Audit/UnAudit)操作
? 实现思路
? 调用Kingdee.BOS.ServiceHelper.dll组件提供的BusinessDataServiceHelper类提供的
SetBillStatus方法
? 插件准备
? 插件工程引用Kingdee.BOS.ServiceHelper.dll组件
? 插件类文件引用BusinessDataServiceHelper所在的命名空间
? BusinessDataServiceHelper.SetBillStatus方法介绍
SetBillStatus方法与SetStatus方法看上去类似,其实完全不一样,其参数列表也完全不一样,调用单据审核操作的服务端要使用SetBillStatus方法,SetStatus方法后续介绍 ? SetBillStatus方法参数介绍 名称 ctx businessInfo pkEntryIds paras 类型 Context BusinessInfo List
? 示例代码 C#
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.List.PlugIn; using Kingdee.BOS.ServiceHelper; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyDynamicFormPlugIn {
[System.ComponentModel.Description(\区分当前类应用在哪个模型上\)] publicclassClass4 : AbstractListPlugIn {
publicoverridevoid ButtonClick(ButtonClickEventArgs e) {
List
newList
KeyValuePair
IOperationResult auditResult = BusinessDataServiceHelper.SetBillStatus( this.Context,
this.View.BusinessInfo,
lstKeyValuePairs, null, \);
//反审核id为10001的当前单据
IOperationResult unAuditResult = BusinessDataServiceHelper.SetBillStatus( this.Context,
this.View.BusinessInfo,
lstKeyValuePairs, null, \); } } }
2.1.4.2. App层插件,如何调用审核/反审核(Audit/UnAudit)操作
? 实现思路
? 调用Kingdee.BOS.App.dll组件提供的ServiceHelper类提供的GetService泛型方法,
获取改变单据状态服务,调用此服务提供的SetBillStatus方法
? 插件准备
? 插件工程引用Kingdee.BOS.App.dll、Kingdee.BOS.Contracts.dll、
Kingdee.BOS.DataEntity.dll
? 类文件引用相关命名空间,详见示例代码
? 接口介绍
? 同Web层插件介绍
? 示例代码 C#
using Kingdee.BOS.Contracts; using Kingdee.BOS.Core.DynamicForm; using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata; using System;
using System.Collections.Generic; using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MyOperaionServicePlugIn {
publicclassClass3 : AbstractOperationServicePlugIn {
publicoverridevoid BeforeExecuteOperationTransaction(
BeforeExecuteOperationTransaction e)
{
//审核\\反审核id为10001的物料数据 //获取单据状态转换服务
ISetStatusService setStatusService =
Kingdee.BOS.App.ServiceHelper.GetService
//获取元数据服务
IMetaDataService metaDataService =
Kingdee.BOS.App.ServiceHelper.GetService
//构建id为10001的数据集合
List object>>(); KeyValuePair FormMetadata materialMetaData = metaDataService.Load(this.Context, \) asFormMetadata; //审核 IOperationResult auditResult = setStatusService.SetBillStatus( this.Context, materialMetaData.BusinessInfo, lstKeyValuePairs, null, \); //反审核 IOperationResult unAuditResult = setStatusService.SetBillStatus( this.Context, materialMetaData.BusinessInfo, lstKeyValuePairs, null, \); } } } 2.1.5. 如何调用禁用(Disabled)操作 2.1.5.1. Web层插件,如何调用禁用(Disabled)操作 ? 实现思路 ? 调用Kingdee.BOS.ServiceHelper.dll组件提供的BusinessDataServiceHelper类所提供 的SetState方法 ? 插件准备 ? 插件工程引用Kingdee.BOS.ServiceHelper.dll组件 ? 插件类文件引用BusinessDataServiceHelper所在的命名空间 ? BusinessDataServiceHelper.SetState方法介绍 ? SetState方法直接操作数据库,执行update语句,按方法参数构建一条例如update xxx set xxx =’ xxx’ where xxx = xxx的指令 ? SetState参数介绍 名称 ctx tableName fieldName fieldValue pkFieldName pkFieldValues 类型 Context string string string string object[] 说明 系统上下文全局信息 待执行update指令的表名 待禁用的状态字段的字段名 待禁用的状态字段的目标值 当前表的唯一标识字段名 当前表的唯一标示字段值集合 ? 示例代码 C# using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.ServiceHelper; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDynamicFormPlugIn { publicclassClass5 : AbstractDynamicFormPlugIn { publicoverridevoid ButtonClick(ButtonClickEventArgs e) { //禁用物料id为10001和10002的数据 BusinessDataServiceHelper.SetState( this.Context, \, \, \, \, newobject[] { 10001, 10002 }); } } } 2.1.5.2. App层插件,如何调用禁用(Disabled)操作 ? 实现思路 ? 调用Kingdee.BOS.App.dll组件提供的ServiceHelper类提供的GetService泛型方法, 访问BusinessDataService服务的SetState方法 ? 插件准备 ? 插件工程引用Kingdee.BOS.App.dll、Kingdee.BOS.Contracts.dll、 Kingdee.BOS.DataEntity.dll ? 类文件引用相关命名空间,详见示例代码 ? 接口介绍 ? 同Web层插件介绍 ? 示例代码 C# using Kingdee.BOS.Contracts; using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyOperaionServicePlugIn { publicclassClass4 : AbstractOperationServicePlugIn { publicoverridevoid BeforeExecuteOperationTransaction( BeforeExecuteOperationTransaction e) { //获取数据服务 IBusinessDataService businessDataService = Kingdee.BOS.App.ServiceHelper.GetService \, newobject[] { 10001, 10002 }); } } } 2.1.6. 如何删除(Delete)单据 2.1.6.1. Web层插件,如何删除(Delete)单据 ? 实现思路 ? 调用Kingdee.BOS.ServiceHelper.dll组件的BusinessDataServiceHelper类提供的Delete 方法 ? 插件准备 ? 插件工程引用Kingdee.BOS.ServiceHelper.dll组件 ? 插件类文件引用BusinessDataServiceHelper所在的命名空间 ? 方法介绍 BusinessDataServiceHelper提供两个Delete方法,其区别在于 ? 参数不带元数据描述信息的,直接执行数据库删除操作,把数据删除 ? publicstaticvoid Delete(Context ctx, object[] Ids, DynamicObjectType dynamicObjectType) ? 参数带元数据描述信息的,执行删除操作的服务端完整服务,如执行删除操作的校 验器、删除操作的服务端服务、删除操作的服务端插件 ? publicstaticIOperationResult Delete(Context ctx, BusinessInfo businessInfo, object[] Ids, OperateOption option = null, string operationNumber = \) ? 参数介绍 名称 ctx Ids dynamicObjectType businessInfo option 类型 Context object[] DynamicObjectType BusinessInfo OperateOption 说明 系统上下文全局信息 待删除数据的id集合 待删除数据的动态实体类型 待删除数据的元数据描述信息 业务控制额外选项,删除的服务端服务和插件都能持有此对象 删除操作的操作码 operationNumber string ? 示例代码 C# using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata; using Kingdee.BOS.ServiceHelper; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDynamicFormPlugIn { publicclassClass6 : AbstractDynamicFormPlugIn { publicoverridevoid ButtonClick(ButtonClickEventArgs e) { //删除id为10001和10002的物料 //获取物料元数据 FormMetadata materialMetadata = MetaDataServiceHelper.Load(this.Context,\) asFormMetadata; //模拟删除服务端操作完整过程 BusinessDataServiceHelper.Delete( this.Context, materialMetadata.BusinessInfo, newobject[] { 10001, 10002 }); } } } 2.1.6.2. App层插件,如何删除单据 ? 实现思路 ? 调用Kingdee.BOS.App.dll组件的ServiceHelper类提供的GetService泛型方法获取删 除服务 ? 插件准备 ? 插件工程引用Kingdee.BOS.App.dll、Kingdee.BOS.Contracts.dll、 Kingdee.BOS.DataEntity.dll ? 类文件引用相关命名空间,详见示例代码 ? 接口介绍 ? 同Web层插件介绍 ? 示例代码 C# using Kingdee.BOS.Contracts; using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyOperaionServicePlugIn { publicclassClass5 : AbstractOperationServicePlugIn { publicoverridevoid BeforeExecuteOperationTransaction( BeforeExecuteOperationTransaction e) { //获取删除服务 IDeleteService deleteService = Kingdee.BOS.App.ServiceHelper.GetService IMetaDataService metaDataService = Kingdee.BOS.App.ServiceHelper.GetService FormMetadata materialMetadata = metaDataService.Load(this.Context,\) asFormMetadata; //执行删除服务的完整过程(推荐方式) deleteService.Delete( this.Context, materialMetadata.BusinessInfo, newobject[] { 10001, 10002 }); //直接执行数据删除 (风险极高,仅适用于未定义单据,只是利用ORM模型存取数据的情况) // 调用此服务会跳过删除校验,仅删除ORM模型内含表格的数据,其他相关数据不会处理,如果有 上下游单据及反写,不会撤销关联及回滚反写,从而造成数据错误! deleteService.Delete( this.Context, newobject[] { 10001, 10002 }, materialMetadata.BusinessInfo.GetDynamicObjectType()); } } } 2.2. 调用单据操作后,如何判断结果,并处理交互提示 ? 操作返回结果接口定义: C# publicinterfaceIOperationResult : IInteractionResult ? IInteractionResult接口定义: C# publicinterfaceIInteractionResult { // 交互表单显示标题 string FormTitle { get; set; } // 交互上下文信息 InteractionContext InteractionContext { get; set; } // 本次交互的发起人 string Sponsor { get; set; } } ? 交互上下文信息定义: C# publicclassInteractionContext { public InteractionContext(); // 当前表单模型信息 publicBusinessInfo BusinessInfo { get; } // 数据上下文 publicContext Context { get; set; } // 交互服务操作的实体集合 publicExtendedDataEntity[] DataEntities { get; set; } // 自定义交互表单的初始化参数:InteractionFormId属性有值时,本属性才生效 publicDynamicFormShowParameter FormShowParameter { get; set; } // 交互表单标识:默认为BOS_K3Displayer publicstring InteractionFormId { get; set; } // 是否交互(发现有领域把此当成单纯的自定义信息提示用,所以加此标识来加以区分)默认是交互类型异常,如作它用,请在此标识 publicbool IsInteractive { get; set; } // K3显示器模型 publicK3DisplayerModel K3DisplayerModel { get; set; } // 其它控制选项 publicOperateOption Option { get; set; } // 简单交互信息(批量自定义消息时,此属性建议赋值,以便平台在批量操作时作简单提示) publicstring SimpleMessage { get; set; }