当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 十六、模块集成流程审批

十六、模块集成流程审批

2020年07月14日  | 移动技术网IT编程  | 我要评论

ERP系统中流程审批是必需的模块,流程审批需要工作流的支持,工作流实现企业业务流程重组(BPR)与系统解耦合,工作流产品有很多,国内的工作流产品比较适合国内项目的业务,国外开源的工作流更接近于标准WfMC,对国内复杂的业务支持不够灵活。通常情况软件公司都会开放适合自己的工作流模块,以适应项目开发。我们开发流程审批也是使用自己开发的流程引擎,流程的定义工具现在没有提供,需要手工配置XML流程模块。

工作流引擎关键接口

启动流程
startWorkflow(processId,startUserId,nextUser.getId(),instanceid,type,
						title,nexttask,url,hmap,flag,testMode);
提交流程
wapi.submitWorkflow(instprocessid,instactivityid,instworkitemid,userIdLst,instanceid,
						type,title,nexttask,url,hmap,flag,testMode);
获取代办列表
getWorkitemList(user.getId(), testMode);
										

工作流模板

<?xml version="1.0" encoding="gb2312"?>
<!--
注意:
流程触发外部接口,其类加载器必须位于工作流引擎类加载器平级或者更高一级
-->
<process id="testwf" name="请款流程" description="">
	<status id="Start" name="开始" type="synchronized" isstart="true">
		<tostatuses>
			<tostatus batchid="tomanager" id="account" name="财务审批" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="sendmail"/>
		</tostatuses>
		<actors>
		</actors>
	</status>
	<status id="draft" name="修改" type="synchronized" isstart="false">
		<tostatuses>
			<tostatus batchid="tomanager" id="account" name="财务审批" condition="false" invoke="" invokecommand=""/>
			<tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/>
		</tostatuses>
		<actors>
			<actor type="variable" id="starter"/>
		</actors>
	</status>
	<status id="account" name="财务审批" type="asynchronized" isstart="false">
		<tostatuses>
			<tostatus batchid="vp" id="vp" name="副总审批" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/>
			<tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/>
			<tostatus batchid="tostarter" id="draft" name="返回修改" condition="false" invoke="" invokecommand=""/>
		</tostatuses>
		<actors>
			<actor type="user" id="fiadmin"/>
		</actors>
	</status>
	<status id="vp" name="副总审批" type="asynchronized" isstart="false">
		<tostatuses>
			<tostatus batchid="tonotice" id="notice" name="通知申请人" condition="false" invoke="" invokecommand=""/>
			<tostatus batchid="tostarter" id="draft" name="返回修改" condition="false" invoke="" invokecommand=""/>
			<tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/>
		</tostatuses>
		<actors>
			<actor type="user" id="sysadmin"/>
		</actors>
	</status>
	<status id="notice" name="通知申请人" type="asynchronized" isstart="false" workflow="outstore" condition="storeName EQ '发货库A(运达)'">
		<tostatuses>
			<tostatus batchid="end" id="end" name="完成" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="outstore"/>
			<tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="outstoredestory"/>
		</tostatuses>
		<actors>
			<actor type="variable" id="starter"/>
		</actors>
	</status>
	<status id="destory" name="作废" type="synchronized" isstart="false">
		<tostatuses>
		</tostatuses>
		<actors>
		</actors>
	</status>
	<status id="end" name="结束" type="synchronized" isstart="false">
		<tostatuses>
		</tostatuses>
		<actors>
		</actors>
	</status>
</process>

模块实体类

package com.gf.model;

import java.io.Serializable;
import java.math.BigDecimal;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;

@TableName("gf_expense")
public class ExpenseInfo implements Serializable{
	@TableId
	private String id = null;
	private String name = null;
	private String company = null;
	private String bank = null;
	private String bankAccount = null;
	private BigDecimal amount = null;
	private String userId = null;
	@TableField(exist=false)
	private String userName = null;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getCompany() {
		return company;
	}
	public void setCompany(String company) {
		this.company = company;
	}
	public String getBank() {
		return bank;
	}
	public void setBank(String bank) {
		this.bank = bank;
	}
	public String getBankAccount() {
		return bankAccount;
	}
	public void setBankAccount(String bankAccount) {
		this.bankAccount = bankAccount;
	}
	public BigDecimal getAmount() {
		return amount;
	}
	public void setAmount(BigDecimal amount) {
		this.amount = amount;
	}
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}	
}

SQL

create table gf_expense(id varchar(32),
	name varchar(100),
	company varchar(100),
	bank varchar(100),
	bankaccount varchar(100),
	amount decimal(10,2),
	userId varchar(100)
);

使用Mybatis-Plus操作数据

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gf.mapper.ExpenseMapper">

</mapper>

package com.gf.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.gf.model.ExpenseInfo;

@Mapper
public interface ExpenseMapper extends BaseMapper<ExpenseInfo>{

}


package com.gf.service;

import com.baomidou.mybatisplus.service.IService;
import com.gf.model.ExpenseInfo;

public interface ExpenseService extends IService<ExpenseInfo>{

}


package com.gf.service.impl;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.gf.mapper.ExpenseMapper;
import com.gf.model.ExpenseInfo;
import com.gf.service.ExpenseService;

@Service
public class ExpenseServiceImpl extends ServiceImpl<ExpenseMapper,ExpenseInfo>
	implements ExpenseService
{

}

模块Controller集成工作流引擎

package com.gf.ctrl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.gf.model.ExpenseInfo;
import com.gf.service.ExpenseService;
import com.gf.statusflow.IOrgModel;
import com.gf.statusflow.IUser;
import com.gf.statusflow.StatusFlowData;
import com.gf.statusflow.StatusFlowMng;
import com.gf.statusflow.StatusFlowWAPI;
import com.gf.statusflow.StatusMsg;
import com.gf.statusflow.UUID;
import com.gf.statusflow.Util;

@Controller
public class ExpenseCtrl {
	@Autowired
	private StatusFlowMng sfmng;
	@Autowired
	private StatusFlowWAPI wapi;
	@Autowired
	private IOrgModel orgmodel;
	@Autowired
	private ExpenseService expserv;

	@RequestMapping("/expense.action")
	public String expense(HttpServletRequest req)
	{
		String instanceid = req.getParameter("instanceid");
		String instprocessid = req.getParameter("instprocessid");
		String instactivityid = req.getParameter("instactivityid");
		String instworkitemid = req.getParameter("instworkitemid");
		StatusMsg wfMsg = null;
		String nexttask = null;
		List<Properties> nextBtnList = null;
		List<Properties> nextActList = null;
		IUser loginUser = Util.getLoginUser();
		String userId = loginUser.getId();
		String processId = "testwf";
		HashMap hmap = null;
		StatusFlowData wfdata = sfmng.getWorkflowData(userId, processId, nexttask, instworkitemid,hmap);
		nextBtnList = wfdata.getNextBtnList();
		nextActList = wfdata.getNextActList();
		req.setAttribute("button", nextBtnList);
		if(instanceid != null)
		{
			ExpenseInfo eps = expserv.selectById(instanceid);
			req.setAttribute("eps", eps);
			req.setAttribute("instprocessid", instprocessid);
			req.setAttribute("instactivityid", instactivityid);
			req.setAttribute("instworkitemid", instworkitemid);
		}
		System.out.println("nextActList==="+nextActList);
		return "/fi/expense";
	}
	
	@RequestMapping("/expsubmit.action")
	@ResponseBody
	public StatusMsg expsave(HttpServletRequest req,ExpenseInfo exps)
	{
		try
		{
			String instanceid = exps.getId();
			if("".equals(Util.fmtStr(instanceid)))
				instanceid = UUID.create("expense");
			String instprocessid = req.getParameter("instprocessid");
			String instactivityid = req.getParameter("instactivityid");
			String instworkitemid = req.getParameter("instworkitemid");
			String nexttask = req.getParameter("nexttask");
			String nextUserId = req.getParameter("nextUserId");
			
			IUser loginUser = Util.getLoginUser();
			String startUserId = loginUser.getId();
			String processId = "testwf";
			String type = "expense";
			IUser nextUser = orgmodel.getUserByLoginId(nextUserId);
			String title = exps.getName()+":"+exps.getAmount().toString();
			String url = "/expense.action";
			HashMap hmap = new HashMap();
			String flag = "gf";
			String testMode = "no";
			exps.setId(instanceid);
			StatusMsg wfMsg = null;
			if("".equals(Util.fmtStr(instworkitemid)))
			{
				expserv.insert(exps);
				System.out.println("nexttask==="+nexttask);
				wfMsg = wapi.startWorkflow(processId,startUserId,nextUser.getId(),instanceid,type,
						title,nexttask,url,hmap,flag,testMode);
			}
			else
			{
				List<String> userIdLst = new ArrayList<String>();
				if(nextUser != null)
					userIdLst.add(nextUser.getId());
				expserv.updateById(exps);
				wfMsg = wapi.submitWorkflow(instprocessid,instactivityid,instworkitemid,userIdLst,instanceid,
						type,title,nexttask,url,hmap,flag,testMode);
			}
			return wfMsg;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
}

JSP页面工作流集成

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<script type="text/javascript" src="/static/easyui/jquery.min.js"></script>
<script type="text/javascript" src="/static/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/static/easyui/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" href="/static/easyui/themes/default/easyui.css"/>
<link rel="stylesheet" href="/static/easyui/themes/icon.css"/>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>财务报销系统</title>
<script>
function wfsubmit(nexttask,nextuserid)
{
	var rtn = $('#frm').form('validate');
	if(!rtn)
		return;
	var nextUserId = '';
	if('end' != nexttask && 'endall' != nexttask && 'destory' != nexttask)
	{
		if(nextuserid == null || nextuserid == '')
		{
			$.messager.alert('错误提示','下一办理人为空!','error');
			return;
		}

		var objdim = nextuserid.split(";");
		for(var k=0;k<objdim.length;k++)
		{
			var objdim2 = objdim[k].split(",");
			if(objdim2[0] == null || objdim2[0] == '')
			{
				$.messager.alert('错误提示','下一办理人为空!','error');
				return;
			}
			nextUserId = objdim2[0];
		}
	}
	var rtn = $('#frm').form('validate');
	if(rtn)
	{
		$('#nexttask').val(nexttask);
		$('#nextUserId').val(nextUserId);
		$('#frm').form('submit', {    
		    url:'/expsubmit.action',    
		    onSubmit: function(){    
	  
		    },    
		    success:function(data){
		    	//alert(data);
		    	$('#buttondiv').empty();
		    }
		});
	}
}
	
</script>
</head>
<body class="easyui-layout">
    <div data-options="region:'center',title:'部门维护'" style="padding:5px;">
    	<div>
    		<img height="100" width="800" src="/downimg.jsp?isorderwf=true&width=600&height=100&processid=testwf&instanceid=${eps.id}&t=<%=new Date()%>"/>
    	</div>
		<form id="frm" method="post">
			<input type="hidden" id="instprocessid" name="instprocessid" value="${instprocessid}"/>
			<input type="hidden" id="instactivityid" name="instactivityid" value="${instactivityid}"/>
			<input type="hidden" id="instworkitemid" name="instworkitemid" value="${instworkitemid}"/>
			<input type="hidden" id="id" name="id" value="${eps.id}"/>
			<input type="hidden" id="nexttask" name="nexttask"/>
			<input type="hidden" id="nextUserId" name="nextUserId"/>
			<input type="hidden" id="userId" name="userId" value="${eps.userId}"/>
		    <div style="margin-left:50px;margin-top:30px">   
		        <input class="easyui-textbox" type="text" id="name" name="name" value="${eps.name}" data-options="width:300,label:'请款名称:'" />   
		    </div>   
		    <div style="margin-left:50px;margin-top:30px"> 
		        <input class="easyui-textbox" type="text" id="company" name="company" value="${eps.company}" data-options="width:300,label:'公司名称:'" />   
		    </div>
		    <div style="margin-left:50px;margin-top:30px"> 
		        <input class="easyui-textbox" type="text" id="bank" name="bank" value="${eps.bank}" data-options="width:300,label:'银行名称:'" />   
		    </div>
		    <div style="margin-left:50px;margin-top:30px"> 
		        <input class="easyui-textbox" type="text" id="bankAccount" name="bankAccount" value="${eps.bankAccount}" data-options="width:300,label:'银行账号:'" />   
		    </div>
		    <div style="margin-left:50px;margin-top:30px"> 
		        <input class="easyui-textbox" type="text" id="amount" name="amount" value="${eps.amount}" data-options="width:300,label:'金额(单位:分):'" />   
		    </div>
  		    <div id="buttondiv" style="margin-left:50px;margin-top:30px">
<%
			List<Properties> button = (List<Properties>)request.getAttribute("button");
			for(Properties prop:button)
			{
				String name = prop.getProperty("name");
				String js = prop.getProperty("js");
%>
				<a id="btn" onclick="<%=js %>" class="easyui-linkbutton"><%=name %></a>
<%
			}
%>  
		    </div>
		</form>
    </div>
</body>
</html>

本文地址:https://blog.csdn.net/qixiang_chen/article/details/85981407

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网