金蝶云星空插件开发记录(一)

实现目的:

新增供应商保存后,触发钉钉审批流程,并根据钉钉审批结果回写是否合格供应商。

实现思路:

通过BOS平台供在应商管理界面新增两个复选框字段:是否钉钉审批、是否合格供应商,若在新建供应商档案时勾选是否钉钉审批,在保存供应商信息的时候调用二开插件传递钉钉审批,同时启动子线程定时任务,定时获取钉钉审批结果,若钉钉审批通过则需要自动回写合格供应商。

实现过程:

1、新建.net framework项目,引入金蝶插件,引入钉钉插件(TopSdk)。

2、新建钉钉帮助类,用于获取token、userid等信息:

cs 复制代码
using DingTalk.Api;
using DingTalk.Api.Request;
using DingTalk.Api.Response;
using System.Collections.Generic;

namespace K3Cloud.BasicData.Supply.SupplySendDing
{
    public class DingtalkHelper
    {
        public static string GetToken() {

            DefaultDingTalkClient defaultDingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
            OapiGettokenRequest OapiGettokenRequest = new OapiGettokenRequest();
            OapiGettokenRequest.Appkey = "你的appkey";
            OapiGettokenRequest.Appsecret = "你的appsecret";
            OapiGettokenRequest.SetHttpMethod("GET");
            OapiGettokenResponse oapiGettokenResponse = defaultDingTalkClient.Execute(OapiGettokenRequest);
            return oapiGettokenResponse.AccessToken;
            
        }

        public static string GetUserId(string token,string name) {
            DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/simplelist");
            OapiUserSimplelistRequest req = new OapiUserSimplelistRequest();
            req.Lang = "zh_CN";
            req.DepartmentId = 51236588;//采购部门id,在钉钉后台查看
            req.SetHttpMethod("GET");
            OapiUserSimplelistResponse rsp = client.Execute(req, token);
            Dictionary<string, string> map = new Dictionary<string, string>();
            rsp.Userlist.ForEach(x =>
            {
                map[x.Name] = x.Userid;

            });
            return map[name];


        }
    }
}

3、新建钉钉流程创建操作类:

cs 复制代码
using DingTalk.Api.Request;
using DingTalk.Api.Response;
using DingTalk.Api;
using System;
using System.Collections.Generic;

namespace K3Cloud.BasicData.Supply.SupplySendDing
{
   public class DingtalkStart
    {
        public static string StartSupplyNew(string token,string userId,string code,string name,string supplyCate,string address) {

            DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/create");
            OapiProcessinstanceCreateRequest req = new OapiProcessinstanceCreateRequest();
            req.AgentId = 39568215863;
            req.ProcessCode = "表单code";
            req.OriginatorUserId = userId;
            req.DeptId = 50212358; //采购部id
            //单行输入框
            List<OapiProcessinstanceCreateRequest.FormComponentValueVoDomain> formComponentValueVoList = new List<OapiProcessinstanceCreateRequest.FormComponentValueVoDomain>();
            OapiProcessinstanceCreateRequest.FormComponentValueVoDomain formComponentValueVo = new OapiProcessinstanceCreateRequest.FormComponentValueVoDomain();
            formComponentValueVoList.Add(formComponentValueVo);
            formComponentValueVo.Name = "编码";
            formComponentValueVo.Value = code;

            OapiProcessinstanceCreateRequest.FormComponentValueVoDomain formComponentValueVo1 = new OapiProcessinstanceCreateRequest.FormComponentValueVoDomain();
            formComponentValueVoList.Add(formComponentValueVo1);
            formComponentValueVo1.Name = "名称";
            formComponentValueVo1.Value = name;

            OapiProcessinstanceCreateRequest.FormComponentValueVoDomain formComponentValueVo2 = new OapiProcessinstanceCreateRequest.FormComponentValueVoDomain();
            formComponentValueVoList.Add(formComponentValueVo2);
            formComponentValueVo2.Name = "日期";
            formComponentValueVo2.Value = DateTime.Now.ToString("yyyy-MM-dd");

            OapiProcessinstanceCreateRequest.FormComponentValueVoDomain formComponentValueVo3 = new OapiProcessinstanceCreateRequest.FormComponentValueVoDomain();
            formComponentValueVoList.Add(formComponentValueVo3);
            formComponentValueVo3.Name = "供应商分组";
            formComponentValueVo3.Value = supplyCate;

            OapiProcessinstanceCreateRequest.FormComponentValueVoDomain formComponentValueVo4 = new OapiProcessinstanceCreateRequest.FormComponentValueVoDomain();
            formComponentValueVoList.Add(formComponentValueVo4);
            formComponentValueVo4.Name = "注册地址";
            formComponentValueVo4.Value = address;

            req.FormComponentValues_ = formComponentValueVoList;
            OapiProcessinstanceCreateResponse rsp = client.Execute(req, token);
            return rsp.ProcessInstanceId;


        }
    }
}

4、封装获取钉钉审批状态类:

cs 复制代码
using DingTalk.Api.Request;
using DingTalk.Api.Response;
using DingTalk.Api;

namespace K3Cloud.BasicData.Supply.SupplySendDing
{
    public class DingtalkGet
    {
        public static string GetSupplyNewField(string processId) {

            DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/get");
            OapiProcessinstanceGetRequest req = new OapiProcessinstanceGetRequest();
            req.ProcessInstanceId = processId;
            OapiProcessinstanceGetResponse rsp = client.Execute(req, DingtalkHelper.GetToken());
            if (rsp.ProcessInstance.Status == "TERMINATED" || rsp.ProcessInstance.Status == "CANCELED") {
                return "否";
            
            }
            if (rsp.ProcessInstance.Result == "refuse")
            {
                return "否";

            }
            if (rsp.ProcessInstance.Status == "COMPLETED" && rsp.ProcessInstance.Result == "agree")
            {

                foreach (var item in rsp.ProcessInstance.FormComponentValues)
                {

                    if (item.Name == "是否转批产")
                    {
                        return item.Value;

                    }
                }

            }
            return null;
        }
    }
}

5、金蝶插件开发:

cs 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.Bill.PlugIn.Args;
using Kingdee.BOS.Util;
using Kingdee.BOS.Log;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.App.Data;
using Kingdee.BOS;
using System.Timers;



namespace K3Cloud.BasicData.Supply.SupplySendDing
{
    /// <summary>
    /// 新增供应商触发钉钉审批
    /// </summary>
    [Description("新增供应商触发钉钉审批")]
    [HotUpdate]
    public class SupplySendDingAfterSaveEventBillPlugIn : AbstractBillPlugIn
    {
        private string token;
        private string instanceId;
        private System.Timers.Timer timer;
        private string isOk;
        private string supplierCode; // 保存供应商编码用于线程中使用

        public override void AfterSave(AfterSaveEventArgs e)
        {
            base.AfterSave(e);

            //是否发送钉钉审批
            var IsSend = this.Model.DataObject["F_UNW_CheckBox_qtr"].ToString();
            if (IsSend == "True")
            {
                //供应商编码
                supplierCode = this.Model.GetValue("FNUMBER").ToString();
                //供应商名称
                var name = this.Model.GetValue("FName").ToString();

                //创建人姓名
                DynamicObject creatorId = (DynamicObject)this.Model.GetValue("FCREATORID");
                var createtorName = creatorId["NAME"].ToString();

                //供应商分组
                var fGroup = (DynamicObject)this.Model.DataObject["FGroup"];
                var fGroupId = fGroup["ID"];
                var sql = "SELECT FNAME FROM T_BD_SUPPLIERGROUP_L WHERE FID= @fid";
                var sqlParam = new SqlParam("@fid", KDDbType.Int64, Convert.ToInt64(fGroupId));
                string fGroupName = "";
                using (var fReader = DBUtils.ExecuteReader(this.Context, sql, sqlParam))
                {
                    while (fReader.Read())
                    {
                        fGroupName = fReader["FNAME"].ToString();
                    }
                }

                //注册地址
                var subEntity = this.View.BillBusinessInfo.GetEntity("FBaseInfo");
                var subObjs = this.Model.GetEntityDataObject(subEntity);
                var address = subObjs[0]["RegisterAddress"].ToString();

                token = DingtalkHelper.GetToken();
                string uid = DingtalkHelper.GetUserId(token, createtorName);

                //触发钉钉流程
                instanceId = DingtalkStart.StartSupplyNew(token, uid, supplierCode, name, fGroupName, address);
                Logger.Error("TEST", "钉钉流程发送成功!", new Exception("无错误"));

                //启动新线程执行定时任务
                Thread timerThread = new Thread(StartTimerTask);
                timerThread.IsBackground = true; // 设置为后台线程
                timerThread.Start();
            }
        }

        /// <summary>
        /// 在新线程中启动定时任务
        /// </summary>
        private void StartTimerTask()
        {
            try
            {
                //1分钟检查一次
                timer = new System.Timers.Timer(60000);
                timer.Elapsed += TimerElapsed;
                timer.AutoReset = true;
                timer.Enabled = true;

                //循环等待审批结果
                while (string.IsNullOrEmpty(isOk))
                {
                    Thread.Sleep(1000); // 减少CPU占用
                }

                //处理审批结果
                if (isOk == "是")
                {
                    var usql = "UPDATE T_BD_SUPPLIER SET F_UNW_CHECKBOX_83G='1' WHERE FNUMBER=@FNo";
                    var sqlParameterList = new List<SqlParam>
                    {
                        new SqlParam("@FNo", KDDbType.AnsiString, supplierCode)
                    };
                    DBUtils.Execute(this.Context, usql, sqlParameterList);
                }

                //清理定时器
                timer.Stop();
                timer.Dispose();
            }
            catch (Exception ex)
            {
                Logger.Error("定时任务处理异常", ex.Message, ex);
            }
        }

        private void TimerElapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                var res = DingtalkGet.GetSupplyNewField(instanceId);
                if (!string.IsNullOrEmpty(res))
                {
                    isOk = res;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("获取审批结果异常", ex.Message, ex);
                isOk = "异常"; // 标记异常状态,退出循环
            }
        }
    }
}

6、将上述代码编译成dll文件,并在bos平台进行注册,重启IIS服务。

相关推荐
chao1898442 小时前
C#模拟鼠标键盘操作的多种实现方案
开发语言·c#·计算机外设
future_studio2 小时前
聊聊 Unity(小白专享、C# 小程序 之 联机对战)
unity·小程序·c#
wuk9982 小时前
C#和NModbus库实现Modbus从站
开发语言·c#
攻城狮CSU6 小时前
类型转换汇总 之C#
java·算法·c#
CodeCraft Studio8 小时前
国产化Word处理控件Spire.Doc教程:用Java实现TXT文本与Word互转的完整教程
java·c#·word·spire.doc·word文档转换·txt转word·word转txt
Aevget8 小时前
DevExpress WinForms v25.1亮点 - 电子表格组件、富文档编辑器全新升级
c#·编辑器·界面控件·devexpress·ui开发·winforms
一个专注写bug的小白猿8 小时前
.net实现ftp传输文件保姆教程
后端·c#·.net
shandianchengzi11 小时前
【记录】Unity|Unity从安装到打开一个Github项目(以我的世界(仿)为例)
unity·c#·游戏引擎·github·我的世界·mc
咕白m62512 小时前
通过 C# 给Word文档添加水印:文字水印、图片水印
后端·c#
YuanlongWang14 小时前
C# 基础——async/await 的实现原理与最佳实践
开发语言·c#