金蝶云星空插件实战开发-新手入门教程-服务插件-自定义校验方法

金蝶云星空插件实战开发-新手入门教程-服务插件-自定义校验方法

1 年前 · 来自专栏 金蝶云星空

阅读对象 :星空系统二次开发新手

需求场景 :在插件开发过程中,实现BOS不容易配置的单据数据校验。实现校验一个单据编号字段必须是11个字符。

开发语言 :C#

开发工具 :Visual Studio 2019

星空版本 :7.6.0

说明:本文前提是开发机已经安装好金蝶云星空系统和金蝶BOS IDE。
星空系统安装部署教程

云星空二次开发基础知识可以浏览以前的文章:

金蝶云星空二次开发-知识地图

金蝶云星空插件实战开发-新手入门教程-表单插件

金蝶云星空插件实战开发-新手入门教程-列表插件

金蝶云星空插件实战开发-新手入门教程-服务插件

金蝶云星空插件实战开发-新手入门教程-自定义WebAPI

本文是承接“ 金蝶云星空插件实战开发-新手入门教程-服务插件 ”这篇教程。是在这篇教程的基础上做的扩展。

如果想要测试本文的代码,必须顺利完成服务插件的教程。打开服务插件的代码项目,在Visual Studio右侧的“解决方案资源管理器”中邮件点击服务插件工程,新建一个类,类名: PurchaseValidator.cs ,如下图所示:

既然创建的一个类文件,那下面就直接敲代码咯,代码如下:

using System;
using Kingdee.BOS;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.Validation;
namespace Test.K3Cloud.SCM.MyAppPlugin
    public class PurchaseValidator : AbstractValidator
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="validateContext"></param>
        /// <param name="ctx"></param>
        public override void InitializeConfiguration(ValidateContext validateContext, Context ctx)
            base.InitializeConfiguration(validateContext, ctx);
            if (validateContext.BusinessInfo != null)
                EntityKey = validateContext.BusinessInfo.GetEntity(0).Key;
        /// <summary>
        /// 自定义校验
        /// </summary>
        /// <param name="dataEntities"></param>
        /// <param name="validateContext"></param>
        /// <param name="ctx"></param>
        public override void Validate(ExtendedDataEntity[] dataEntities, ValidateContext validateContext, Context ctx)
            if (validateContext.IgnoreWarning)
                return; //警告已经被用户忽略,就不需要再次执行了
            if (dataEntities == null || dataEntities.Length <= 0)
                return;
            // 循环校验每一个数据包(一个数据包对应一张单据)
            foreach (var et in dataEntities)
                // 订单编号在单据数据包中的字段名为:BillNo
                string billNo = Convert.ToString(et.DataEntity["BillNo"]);
                if (billNo.Length != 11)
                    validateContext.AddError(et, new ValidationErrorInfo(
                       "BillNo",                                        // 出错的字段Key,可以空
                       Convert.ToString(et.DataEntity[0]),              // 数据包内码,必填,后续操作会据此内码避开此数据包
                       et.DataEntityIndex,                              // 出错的数据包在全部数据包中的顺序
                       et.RowIndex,                                     // 出错的数据行在全部数据行中的顺序,如果校验基于单据头,此为0
                       "Error 0",                                       // 错误编码,可以任意设定一个字符,主要用于追查错误来源
                       "数据校验未通过,单据编号必须是11个字符",        // 错误的详细提示信息
                       "单据合法性检查",                                // 错误的简明提示信息
                       ErrorLevel.FatalError                            // 错误级别

自定义校验器类需要继承 AbstractValidator 类。在自定义校验器类中,dataEntities 为客户端传递过来的单据的数据。可以多个单据同时操作,所以这里,单据数据是一个数组。上面代码中 et.DataEntity 是某个单据的数据包。

接下来我们在服务插件中注册自定义校验器。为了方便大家顺利阅读代码,下面将服务插件的完整代码贴出来。如下面代码所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kingdee.BOS;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Interaction;
using Newtonsoft.Json.Linq;
namespace Test.K3Cloud.SCM.MyAppPlugin
    public class Class1: AbstractOperationServicePlugIn
        // SpensorKey
        private const string SpensorKey = "DefaultSpensorKey";
        /// <summary>
        /// 单据校验。
        /// </summary>
        /// <param name="e"></param>
        public override void OnAddValidators(AddValidatorsEventArgs e)
            base.OnAddValidators(e);
            var purchaseValidator = new PurchaseValidator();
            e.Validators.Add(purchaseValidator);    // 注册自定义校验器
        public override void EndOperationTransaction(EndOperationTransactionArgs e)
            base.EndOperationTransaction(e);
            // 当保存订单时
            if (FormOperation.OperationName == "保存")
                /// 构造错误信息
                JArray errMsg = new JArray {
                    new JValue("01"),
                    new JValue("这是一条提示信息")
                bool ignore = false;    // 窗口显示状态,默认不显示
                Option.TryGetVariableValue(SpensorKey, out ignore);
                if (!ignore && !Option.HasInteractionFlag(SpensorKey))
                    KDInteractionException ie = ShowErrorMsg(Context, SpensorKey, ignore, errMsg);
                    throw ie;
        /// <summary>
        /// 信息提示窗口
        /// </summary>
        /// <param name="context">上下文对象</param>
        /// <param name="spensorKey">窗口标识</param>
        /// <param name="ignore">状态</param>
        /// <param name="errorMsg">错误信息</param>
        /// <returns></returns>
        public static KDInteractionException ShowErrorMsg(Context context, string spensorKey, bool ignore, JArray errorMsg)
            if (errorMsg.Count() != 2)
                return null;
            string titleMsg = "代码~|~信息";
            string errMsg = "{0}~|~{1}";
            K3DisplayerModel model = K3DisplayerModel.Create(context, titleMsg);
            model.AddMessage(string.Format(errMsg, errorMsg[0].ToString(), errorMsg[1].ToString()));
            model.Option.SetVariableValue(K3DisplayerModel.CST_FormTitle, "单据操作有以下信息出错,需要继续吗?");
            model.OKButton.Caption = new LocaleValue("是");
            model.CancelButton.Visible = model.OKButton.Visible = true;
            model.CancelButton.Caption = new LocaleValue("否");
            KDInteractionException ie = new KDInteractionException(spensorKey);
            ie.InteractionContext.InteractionFormId = "BOS_K3Displayer";
            ie.InteractionContext.K3DisplayerModel = model;