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

实现目的:

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

实现思路:

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

实现过程:

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

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

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、新建钉钉流程创建操作类:

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、封装获取钉钉审批状态类:

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、金蝶插件开发:

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服务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/922330.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/922330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业跨区域组网新解:SD-WAN技术打造安全稳定网络体系

前言在数字化浪潮席卷全球的今天&#xff0c;企业跨区域网络互联已成为支撑业务发展的关键基础设施。传统MPLS专线虽性能稳定&#xff0c;但高昂成本和漫长部署周期令众多企业望而却步。SD-WAN技术的出现&#xff0c;正以其智能、灵活和成本效益的优势&#xff0c;重塑企业组网…

Docker 容器化

引言在解释docker是什么之前&#xff0c;我们首先应该先了解的是容器化的概念。什么是容器&#xff1f;就是一个沙箱&#xff0c;在这个沙箱中涵盖了特定应用运行的一切依赖的内容。但他不是一个操作系统&#xff0c;且和底层的操作系统是隔离的。什么是容器化&#xff1f;容器…

LeetCode刷题——hot 100(3)

题目1&#xff1a;矩阵置零题目&#xff1a;问题分析&#xff1a;使用两个布尔数组来分别记录哪行哪列出现了0&#xff0c;当出现0的行和列&#xff0c;对应的布尔数组值置为true。再次遍历数组&#xff0c;当出现行数组和列数组中的值为true&#xff0c;则对应的原数组的值置为…

Ajax-day2(图书管理)-渲染列表

本篇笔记素材来自“黑马程序员” 渲染列表图书管理一、获取数据二、渲染数据完整代码图书管理 Bootstrap 框架渲染列表&#xff08;查&#xff09;新增图书&#xff08;增&#xff09;删除图书&#xff08;删&#xff09;编辑图书&#xff08;改&#xff09; 自己的图书数据&a…

MOS管的电路

MOS管的三极都会存在以下三个电容&#xff0c;分别是&#xff1a;Cgs,Cgd,Cds 输入电容CissCgsCgd 输出电容CossCgdCds 反向传输电容CrssCgd&#xff0c;也叫米勒电容 然而&#xff0c;这三个等效电容是构成串并联组合关系&#xff0c;他们并不是独立的&#xff0c;而是相互…

STM32_05_时钟树

时钟 d用来输入数据&#xff0c;CLK就是我们的时钟&#xff0c;CPU1s中72000000HZ个时钟周期STM32的时钟树锁相环HSE时钟源HSI时钟源LSE时钟源LSI时钟源SystemInit函数SetSysClock函数SetSysClockTo72函数SystemInit()后时钟频率大小总结RCC标准库函数定义变量a&…

C语言---判断语句

文章目录1. if 语句2. if...else 语句3. if...else if...else 语句4. switch 语句5. 三元运算符 ( ? : )总结与对比如何选择C语言中的判断语句用于根据给定的条件来决定执行哪一段代码。其核心是条件为真&#xff08;必须&#xff09;则执行一段代码&#xff0c;条件为假&…

[硬件电路-212]:电流的本质确实是电子的移动

1. 微观机制&#xff1a;电子的定向漂移与热运动定向漂移&#xff08;Drift Motion&#xff09;&#xff1a;在导体&#xff08;如金属&#xff09;中&#xff0c;自由电子&#xff08;价电子&#xff09;受电场驱动&#xff0c;从负端向正端定向移动&#xff0c;形成宏观电流。…

双RFSOC47DR-16通道5GSPS ADC采集模块

16通道5GSPS ADC采集板卡组成如图1所示。该板卡的输入接口为SMA单端输入&#xff0c;ADC采集和处理采用Xilinx公司的XCZU47DR-2FFVE1156I芯片。板卡需配备4路QSFP28光口输出&#xff0c;并需要集成网口、DDR4、SD卡、USB调试口。两块RF-Soc需确保连接通信功能。板卡的16通道需实…

pytest -- 中文文档

前言 零基础1小时快速入门pytest自动化测试教程&#xff0c;全套项目框架实战pytest配置文件可以改变pytest的运行方式&#xff0c;它是一个固定的文件pytest.ini文件&#xff0c;读取配置信息&#xff0c;按指定的方式去运行 非test文件 pytest里面有些文件是非test文件 pyt…

硬件开发2-ARM裸机开发3-IMX6ULL - 引入中断

一、铺垫引入中断 → 按键1、概要&#xff1a;实现按键控制发光二极管和蜂鸣器输入类型的外设&#xff1a;按键&#xff08;key&#xff09;2、参考手册内容完成配置过程&#xff08;1&#xff09;key 按键原理图&#xff08;2&#xff09;core 内核中命名 -- UART1 CTS&#x…

Ansible的 Playbook 模式详解

目录一、Playbook模式1.1 Playbook 的优势1.2 Playbook 的组成1.3 安装 httpd 服务案例1.4 Playbook 命令及常用参数1.5 Playbook 的语法 —— 权限相关1. remote_user2. become3. become_method1.6 Playbook 的通知与触发机制1. notify2. handlers3. 使用示例4. 使用场景1.6 P…

猿辅导Java后台开发面试题及参考答案

int 与 Integer 的区别是什么&#xff1f;若创建数量庞大的数字时使用 Integer&#xff0c;会对重复数字创建新对象吗&#xff1f;int 是 Java 中的基本数据类型&#xff0c;直接存储数值&#xff0c;占用 4 个字节&#xff0c;默认值为 0&#xff0c;不需要通过 new 关键字创建…

代码随想录学习摘抄day9(回溯1-11)

一个朴实无华的目录定义&#xff1a;回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。应用场景&#xff1a;回溯法解决的问题都可以抽象为树形结构代码模板题型第77题. 组合思路&#xff1a;每次从集合中选取元素&#xff0c;可选择的范围随着选择的进行而收缩&…

Altium Designer(AD24)打开工程文件的几种方法

🏡《专栏目录》 目录 1,概述 2,源文件 2,菜单栏 4,工具栏 5,注意事项 1,概述 本文介绍几种打开工程文件的方法。 2,源文件 找到工程的源文件存储路径,找到.PrjPcb的源工程文件,双击打开。 2,菜单栏 第1步:执行File→Open, 第2步:找到工程文件的存储路径,并选中…

Linux嵌入式自学笔记(基于野火EBF6ULL):2.点灯与ubuntu安装

一、点灯登录root&#xff1a;账号&#xff1a;root ; 密码&#xff1a;root点灯命令&#xff1a;echo 0 > /sys/class/leds/red/brightness #关闭red灯 echo 0 > /sys/class/leds/blue/brightness #关闭blue灯 echo 0 > /sys/class/leds/green/brightness …

【Java实战㊷】Java实战:MyBatis-Plus 开启MySQL数据库高效操作之旅

目录 一、MyBatis-Plus 环境集成 1.1 项目依赖引入 1.2 数据库配置 1.3 代码生成器使用 二、核心 CRUD 操作实现 2.1 基础查询 2.2 数据新增与修改 2.3 复杂查询场景 三、性能优化与高级特性 3.1 缓存配置 3.2 乐观锁实现 3.3 字段自动填充 四、实战案例:用户管理模块开发 4.1…

开学季干货——知识梳理与经验分享

技术文章大纲&#xff1a;开学季干货——知识梳理与经验分享目标受众分析明确文章面向的学生群体&#xff08;如大学生、高中生&#xff09; 分析不同群体的核心需求&#xff08;课程准备、时间管理、工具使用&#xff09; 结合技术场景&#xff08;如数字笔记、在线协作&#…

Linux《线程(上)》

通过之前的学习我们已经了解了操作系统当中的基本的概念包括进程、基础IO、磁盘文件存储等&#xff0c;但是到目前为止我们还未了解到线程相关的概念&#xff0c;这就使得当前我们对操作系统的认知还不是完整的&#xff0c;现在我们是还是无法理解一个进程当中是如何同时的执行…

为什么知识复用时缺乏场景化指导影响实用性

知识复用时因缺乏场景化指导而严重影响实用性&#xff0c;其根本原因在于知识的价值本质上根植于其应用情境。脱离了场景的“纯知识”往往是抽象、片面且难以行动的。这导致了认知鸿沟的产生、隐性知识的流失、决策风险的增加、以及学习迁移效率的低下。当使用者面对一份缺乏“…