审批工作流—ccflow

news2024/11/27 14:40:38

审批工作流—ccflow

  • 目录
    • 概述
      • 需求:
    • 设计思路
    • 实现思路分析
      • 1.java 代码分析
  • 参考资料和推荐阅读

Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.

目录

在这里插入图片描述

概述

审批工作流—ccflow

需求:

设计思路

实现思路分析

1.java 代码分析

Ccflow的审批有多种方式,可以根据实际需要,选择相应的审批方式。

系统的来说,审批有两部分组成:功能按钮、审批意见栏或者审批组件组成。

先介绍下与审批相关的功能按钮:

  1. 退回:如果审批不通过,或者文件、表单内容错误、或是其他问题,可以进行退回,进行修改内容或是重新提交等操作。

  2. 在cc中,退回分为以下几种模式:不能退回、退回到指定节点(步骤)、退回任意节点(步骤)、只能退回上一个节点。

  3. 挂起:相当于暂停的意思,分为永久挂起和定时挂起;挂起后,也可以解除。

  4. 抄送:相当于email的抄送,在政府单位中也可以叫做知会、阅知等词语。就是想当前的工作抄送给另一个人,让其知道。

  5. 加签:如果感觉自己需要参考其他人的意见,就使用加签,将工作附加给另一个人处理。

  6. 移交:如果感觉工作不是自己负责的范围内,或者自己的权限不够,可以使用移交,将工作移交给其他人处理。

审批意见栏:

  1. 使用审核组件:审核组件是cc的流程表单设计器自带的组件,直接拖拽到表单中就可以使用。邮件审核组件,可以进行功能编辑与权限控制,如下图:

流程运行中的效果图如下:

审核组件可以在多种表单中使用,例如:自由表单、SDK表单、树表单、自定义表单等。

  1. 在表单中自定义审批意见栏。可以按照自己的想法或需求进行设计。

CCFLOW源码解读系列01-----发起流程

1、发起流程、
发起流程时主要做了两件事:一是写入业务数据表,二是新建一条审批流程记录。

发起流程的方法

public static Int64 Node_CreateStartNodeWork(string flowNo, Hashtable htWork = null, DataSet workDtls = null,
            string flowStarter = null, string title = null, Int64 parentWorkID = 0, string parentFlowNo = null, int parentNDFrom = 0

系统中一般这样调用、

Hashtable ht = new Hashtable();
long startFlowId = Dev2Interface.Node_CreateStartNodeWork(fk_Flow, ht, null, currentUserName, titl

传入的主要参数有:
流程的编号fk_Flow,编号是从001开始的,工作流系统中有一个默认的流程,编号是001,你可以在上面修改,也可以新建,新建后的流程编号是002.
键值对,ht主要是用于修改业务表。
currentUserName 用户名,主要用于初始化发起人信息,如果传NULL,则会默认用当前登录用户。
titile 流程名,如果传Null,则会默认生成一条流程。
进入方法,会看到初始化了几个实例 :
一是流程对象 Flow 记录了流程的编号、创建时间、名称,

Flow fl = new Flow(flowNo);

/// <summary>
        /// 流程
        /// </summary>
        /// <param name="_No">编号</param>
        public Flow(string _No)
        {
            this.No = _No;
            if (SystemConfig.IsDebug)
            {
                int i = this.RetrieveFromDBSources();
                if (i == 0)
                    throw new Exception("流程编号不存在");
            }
            else
            {
                this.Retrieve();
            }
        }

二是 节点对象 Node 存放每个节点的信息,通过流程的开始节点ID初始化节点类

Node nd = new Node(fl.StartNodeID);
让我们看看流程开始节点是如何找到的,如下,开始节点等于流程号+01 再转成Int 也就是说流程编号为002的开始节点为201。

public int StartNodeID
        {
            get
            {
                return int.Parse(this.No + "01");
                
            }
        }

三是操作员 Emp

/// <summary>
        /// 操作员
        /// </summary>
        /// <param name="no">编号</param>
        public Emp(string no)
        {
            if (no == null || no.Length == 0)
                throw new Exception("@要查询的操作员编号为空。");

            this.No = no.Trim();
           
                this.Retrieve();
            
        }

三是工作对象 work 随着该对象被创建,对象GenerWorkFlow也被创建出来,对应的表wf_generworkflow 中增加了一条记录

Work wk = fl.NewWork(flowStarter);

public Work NewWork(string empNo)
        {
            Emp emp = new Emp(empNo);
            return NewWork(emp, null);
        }
        /// <summary>
        /// 产生一个开始节点的新工作
        /// </summary>
        /// <param name="emp">发起人</param>
        /// <param name="paras">参数集合,如果是CS调用,要发起子流程,要从其他table里copy数据,就不能从request里面取,可以传递为null.</param>
        /// <returns>返回的Work.</returns>
        public Work NewWork(Emp emp, Hashtable paras)
        {
            // 检查是否可以发起该流程?
            if (Glo.CheckIsCanStartFlow_InitStartFlow(this) == false)
                throw new Exception("err@您违反了该流程的【" + this.StartLimitRole + "】限制规则。" + this.StartLimitAlert);

            GenerWorkFlow gwf = new GenerWorkFlow();

........................

wf_generworkflow表中修改的字段如下,WorkID是启动流程的唯一标识,也是最终要返回的ID,可以绑定在业务表上的。设置了当前流程的状态:WFState.Blank。

#region 给 generworkflow 初始化数据. add 2015-08-06

        gwf.FK_Flow = this.No;
        gwf.FK_FlowSort = this.FK_FlowSort;
        gwf.SysType = this.SysType;
        gwf.FK_Node = nd.NodeID;
        gwf.WorkID = wk.OID;
        gwf.WFState = WFState.Blank;
        gwf.FlowName = this.Name;

        gwf.FK_Node = nd.NodeID;
        gwf.NodeName = nd.Name;
        gwf.Starter = WebUser.No;
        gwf.StarterName = WebUser.Name;
        gwf.FK_Dept = BP.Web.WebUser.FK_Dept;
        gwf.DeptName = BP.Web.WebUser.FK_DeptName;

接下来又对 GenerWorkerList对象进行了修正,

#region 为开始工作创建待办
            GenerWorkFlow gwf = new GenerWorkFlow();
            gwf.WorkID = wk.OID;
            int i = gwf.RetrieveFromDBSources();

            gwf.FlowName = fl.Name;
            gwf.FK_Flow = flowNo;
            gwf.FK_FlowSort = fl.FK_FlowSort;
            gwf.SysType = fl.SysType;

            gwf.FK_Dept = emp.FK_Dept;
            gwf.DeptName = emp.FK_DeptText;
            gwf.FK_Node = fl.StartNodeID;

            gwf.NodeName = nd.Name;

            //默认是空白流程
            //gwf.WFSta = WFSta.Etc;
            gwf.WFState = WFState.Blank;
            //保存到草稿
            if (fl.DraftRole == DraftRole.SaveToDraftList)
            {
                gwf.WFState = WFState.Draft;
            }
            else if (fl.DraftRole == DraftRole.SaveToTodolist)
            {
                //保存到待办
                //  gwf.WFSta = WFSta.Runing;
                gwf.WFState = WFState.Runing;
            }

            if (DataType.IsNullOrEmpty(title))
            {
                gwf.Title = BP.WF.WorkFlowBuessRole.GenerTitle(fl, wk);
            }
            else
            {
                gwf.Title = title;
            }

            gwf.Starter = emp.No;
            gwf.StarterName = emp.Name;
            gwf.RDT = DataType.CurrentDataTime;

            if (htWork != null && htWork.ContainsKey("PRI") == true)
            {
                gwf.PRI = int.Parse(htWork["PRI"].ToString());
            }

            if (htWork != null && htWork.ContainsKey("SDTOfNode") == true)
            {
                /*节点应完成时间*/
                gwf.SDTOfNode = htWork["SDTOfNode"].ToString();
            }

            if (htWork != null && htWork.ContainsKey("SDTOfFlow") == true)
            {
                /*流程应完成时间*/
                gwf.SDTOfNode = htWork["SDTOfFlow"].ToString();
            }

            gwf.PWorkID = parentWorkID;
            gwf.PFlowNo = parentFlowNo;
            gwf.PNodeID = parentNDFrom;
            if (i == 0)
            {
                gwf.Insert();
            }
            else
            {
                gwf.Update();
            }

四是创建了工作者列表GenerWorkerList,写入的表是wf_generworkerlist

/ 产生工作列表.
GenerWorkerList gwl = new GenerWorkerList();
gwl.WorkID = wk.OID;
if (gwl.RetrieveFromDBSources() == 0)
{
gwl.FK_Emp = emp.No;
gwl.FK_EmpText = emp.Name;

            gwl.FK_Node = nd.NodeID;
            gwl.FK_NodeText = nd.Name;
            gwl.FID = 0;

            gwl.FK_Flow = fl.No;
            gwl.FK_Dept = emp.FK_Dept;
            gwl.FK_DeptT = emp.FK_DeptText;


            gwl.SDT = "无";
            gwl.DTOfWarning = DataType.CurrentDataTime;
            gwl.IsEnable = true;

            gwl.IsPass = false;
            //     gwl.Sender = WebUser.No;
            gwl.PRI = gwf.PRI;
            gwl.Insert();
        }

最后,整个启动流程的方法会将OID返回:
return wk.OID;
可以返回的ID绑定在自定义的业务表中。

参考资料和推荐阅读

1.https://blog.csdn.net/jflows/article/details/4669731

欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~
如有侵权,请私信联系删除之。

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

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

相关文章

LeetCode[547]省份数量

难度&#xff1a;中等题目&#xff1a;有 n个城市&#xff0c;其中一些彼此相连&#xff0c;另一些没有相连。如果城市 a与城市 b直接相连&#xff0c;且城市 b与城市 c直接相连&#xff0c;那么城市 a与城市 c间接相连。省份 是一组直接或间接相连的城市&#xff0c;组内不含其…

Leetcode:93. 复原 IP 地址(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 回溯&#xff1a; 原理思路&#xff1a; 问题描述&#xff1a; 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。…

leetcode刷题记录总结-2.链表

文章目录一、重排列表[1. 奇偶链表](https://leetcode.cn/problems/odd-even-linked-list/solutions/)题解二、链表的增、删、改、查[203. 移除链表元素](https://leetcode.cn/problems/remove-linked-list-elements/)题解不简洁代码简洁代码707.设计链表题解不简洁代码优化后的…

mysql主从复制配置(windows和linux操作都有)

我是目录主从复制是什么&#xff1f;操作实践验证主从设置主从复制是什么&#xff1f; mysql主从复制是一个异步的复制过程&#xff0c;底层是基于mysql数据库自带的二进制日志功能。就是一台或多台mysal数据库&#xff08;slave&#xff0c;即从库&#xff09;从另一台mysql数…

macOS Big Sur 11.7.3 (20G1116) 正式版 ISO、PKG、DMG、IPSW 下载

本站提供的 macOS Big Sur 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。 请访问原文链接&#xff1a;https://sysin.org/blog/macOS-Big-Sur/&#xff0…

【Python百日进阶-Web开发-Linux】Day236 - Win11安装Windows Subsystem for Android(WSA)

文章目录一、Win11运行安卓app前提条件二、Win11运行安卓app支持以下新特性三、Win11运行安卓app操作步骤3.1 修改定位3.2 开启VT虚拟化3.3 开启电脑的Hyper-V和虚拟机平台四、WSA下载4.1 百度网盘下载4.2 store.rg-adguard.net下载五、WSA安装&#xff08;没有成功&#xff0c…

C++初阶--继承

目录 继承的概念 继承定义 继承基类成员访问方式 基类和派生类对象的赋值转换 继承中的作用域 派生类的默认成员函数 友元关系不能继承 基类static成员 菱形继承与菱形虚拟继承 虚拟继承解决数据冗余和二义性的原理 继承和组合 继承的概念 继承是类层次的复用。 继…

Golang 泛型学习

Golang 泛型 今天来学习下Golang中泛型的基础知识。使用泛型&#xff0c;开发者可以声明一个函数来适应不同类型的参数&#xff0c;避免由于参数类型不一致而声明多个处理逻辑类似的函数。在本教程中&#xff0c;将声明两个简单的非泛型函数&#xff0c;然后在单个泛型函数中实…

这些实体店直播必备技巧,新手直接套用就能火!

随着直播的受众越来越广、门槛越来越低&#xff0c;入局服装直播的实体店越来越多。对于服装厂商来说&#xff0c;服装产业链越靠下游毛利率越高&#xff0c;品牌商和销售商利润远高于加工生产商&#xff0c;约在40-50%&#xff0c;而服装制造商的毛利率仅在15%左右。而对于本土…

JDK8 新特性之收集Stream流中的结果

目录 一&#xff1a;Stream流中的结果到集合中 二&#xff1a;Stream流中的结果到数组中 三&#xff1a;对流中数据进行聚合计算 四&#xff1a;对流中数据进行分组 五&#xff1a;对流中数据进行多级分组 六&#xff1a;对流中数据进行分区 七&#xff1a;对流中数据进行拼接…

8.Java循环高级综合练习-无限循环和跳转控制语句,逢七过,平方根,判断是否为质数,猜数字小游戏

文章目录前言一、无限循环1.这三种循环中哪一种无限循环是最常用的呢?2.注意事项:二、跳转控制语句三、逢七过四、平方根五、判断该整数是否为一个质数六、猜数字小游戏保底机制总结前言 一、无限循环 1.这三种循环中哪一种无限循环是最常用的呢? 当然是右上角的while循环啦…

【若依】若依字典管理页面中列表按钮功能的实现

0. 功能实现描述 1. 代码实现 ScStfController.java /*** 查询员工证书* param stfId* param modelMap* return*/ RequiresPermissions("sc:stf:cert") GetMapping("/cert/{stfId}") public String detail(PathVariable("stfId") Long stfId, …

结构型模式-组合模式

1.概述 对于这个图片肯定会非常熟悉&#xff0c;上图我们可以看做是一个文件系统&#xff0c;对于这样的结构我们称之为树形结构。在树形结构中可以通过调用某个方法来遍历整个树&#xff0c;当我们找到某个叶子节点后&#xff0c;就可以对叶子节点进行相关的操作。可以将这颗树…

谷粒学院——Day19【项目部署】

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

Java中的hashCode,真的很容易弄懂

写这篇文章是因为在看hashMap源码时遇到有什么hashcode值&#xff0c;然后就去查&#xff0c;脑袋里面是有印象的&#xff0c;不就是在Object中有equals和hashcode方法嘛&#xff0c;这在学java基础的时候就遇到过&#xff0c;不过那时候无所谓&#xff0c;囫囵吞枣&#xff0c…

三、python基础语法进阶篇(黑马程序猿-python学习记录)

黑马程序猿的python学习视频&#xff1a;https://www.bilibili.com/video/BV1qW4y1a7fU/ 目录 一、文件操作 一、 文件的读取 1. 打开文件open() 2. 读取文件10个字节read(10) 3. 读取文件全部信息read() 4. 读取文件readLines() 5. 读取文件readLine() 6. for循环读取…

Nginx与LUA(7)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客。值此新春佳节&#xff0c;我给您拜年啦&#xff5e;祝您在新的一年中所求皆所愿&#xff0c;所行皆坦途&#xff0c;展宏“兔”&#xff0c;有钱“兔”&#xff0c;多喜乐&#xff0c;常安宁&#xff01;软件开发中&…

使用小程序+网页简易实现多客户端实时弹幕

此文主要通过小程序网页模拟多客户端通过轮询、WebSockets、订阅推送等方式简易实现实时弹幕。 实现流程1、服务端1.1、创建项目2.2、接口定义2、客户端2.1、小程序端2.2、web端3、实现方式3.1、轮询3.2、WebSocket3.3、订阅推送实现流程 1、服务端 1.1、创建项目 打开Visual…

【docker概念和实践 5】容器命令和案例(1)

一、说明 docker的四个要素是&#xff1a;本地的Docker-engine、网上&#xff08;本地&#xff09;的仓库、镜像images、容器&#xff1b;初学者必须了解这是个概念的关系。但是&#xff0c;真正重要的概念是容器&#xff0c;因为&#xff0c;只有掌握了容器&#xff0c;才能具…

SpringBoot整合SSM

添加pom依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version><scope>provided</scope></dependency><dependency><groupId>org.mybati…