情景引入
小白:咯咯咯咯咯咯,,,鸡都叫了好久了,你怎么还在睡。。
我:好好的五一假期,怎么不能让我多睡会么~
我:鸡只是叫了,说不定它现在又在趴着睡觉了呢。怎么,你又遇到什么事了吗?
小白:我看了你的手把手教你如何玩转自定义工作流(一),对工作流有了理论上的理解,但是具体的情况还需要怎么做呢?
我:理论可是非常重要的,而实践就是检验真理的唯一标志。
小白:那你赶紧接着上一篇文章来继续跟我讲解讲解呗。
我:你理论都可以了,我觉得也应该差不多可以实现了
小白:不行,还是存在好多的问题,感觉好复杂。
我:emmm,工作流你要做得复杂,后面的操作逻辑当然复杂呢~
我:我好想轻松一会~~好久没有自然醒了!
小白:你休想偷懒,我可还一直等着的呢!
我:好吧。那咱们就来继续完善一下。求知欲这么强,要继续努力!
小白:我去搬凳子去啦!
我:别忘记还有瓜子。。。。
前导
首先把理论知识弄懂,赶紧点点这个文章:
(1)工作流理论知识
手把手教你如何玩转自定义工作流
https://blog.csdn.net/Cs_hnu_scw/article/details/89574312
(2)如果已经有一定基础了,可以看看开源框架是如何实现
Activiti工作流开源框架
https://blog.csdn.net/Cs_hnu_scw/article/details/79059965
简述
在上一篇文章中,我对工作流的相关理论进行了非常详细的讲解,并且对如何设计数据库表进行了透彻的分析。如果,你有认真学习的话,我就得就可以独立开发代码了。但是,咱们既然有了理论,那么当然还需要实践证明一下理论是否可行。因此,在本篇文章中,主要是对系统功能的实现的大体讲解,大家可以根据自身的需要进行参考。
那么我们一起来看看,如果实现工作流吧!
数据库设计
手把手教你如何玩转自定义工作流
https://blog.csdn.net/Cs_hnu_scw/article/details/89574312
对于这个的话,我在前面一篇文章已经讲解的非常详细了,所以,这篇就不再过多阐述,这里的话,自己就把完整的一个数据库表结构放一下图。(在源代码中,有原始的SQL内容)
操作界面
操作界面,在前面一篇文章也进行了讲解,但是对页面有些修改,因为自己去掉了过多复杂的前端显示效果,因为主要是为了介绍工作流的实现,那些华丽页面不是我的重点。(毕竟我只是一个后端,前端马马虎虎~~要求不能太高)
(哈哈,再推一次)
手把手教你如何玩转自定义工作流(一)
https://blog.csdn.net/Cs_hnu_scw/article/details/89574312
开发环境
(1)Windows7 旗舰版
(2)IDEA 2017.2.5
(3)Spring + SpringMVC + Mybatis(SSM常用框架)
(4)Mysql 5.7.17
(5)Navicat
以上是自己的开发环境介绍,不一定需要完全一样,只需要能够实现同样的结果即可。(比如,windows7我是因为电脑太老了而且个人习惯了)
项目结构示意图
(1)pojo实体
(2)Controller
(3)Service
(4)Mapper
(5)MapperXml
(6)配置文件
(7)前端页面
备注:
(1)Java的源文件都是处于同一级目录
(2)配置文件都在resource目录
(3)前端相关的都在webapp目录下。
开发步骤
接下来,我们就根据上一篇文章提到的理论知识来进行手把手的教学!(一定要结合上篇文章哦,否则会看不懂的!)
-
构建SSM的基本框架
关于这个,我这里不多说,大家可以看我的另外的文章,保证包学包会。
手把手教你如何玩转SSM框架的构建
https://blog.csdn.net/Cs_hnu_scw/article/details/80709822 -
添加审批人员
界面效果:
JSP页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
<base href="<%=basePath%>">
<meta charset="utf-8" />
<title></title>
<meta name="description" content="overview & stats" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="static/css/bootstrap.min.css" rel="stylesheet" />
<link href="static/css/bootstrap-responsive.min.css" rel="stylesheet" />
<link rel="stylesheet" href="static/css/font-awesome.min.css" />
<!-- 下拉框 -->
<link rel="stylesheet" href="static/css/chosen.css" />
<link rel="stylesheet" href="static/css/ace.min.css" />
<link rel="stylesheet" href="static/css/ace-responsive.min.css" />
<link rel="stylesheet" href="static/css/ace-skins.min.css" />
<script type="text/javascript" src="static/js/jquery-1.7.2.js"></script>
<!--提示框-->
<script type="text/javascript" src="static/js/jquery.tips.js"></script>
</head>
<body>
<form action="/addapprover" name="addApproverForm" id="addApproverForm" method="post">
<!--这个就从系统里面的用户那里获得-->
<input type="hidden" name="user_Id" id="user_Id" value="213"/>
<div id="zhongxin">
<table>
<tr><h7>用户姓名:</h7></tr>
<tr>
<td>
<input type="text" name="user_Name" id="user_Name" placeholder="用户姓名" title="姓名"/>
</td>
</tr>
<tr>
<td>
<textarea rows="8" cols="80" placeholder="输入审批人描述信息" style="width: 500px;" name="approver_Description" id="approver_Description"></textarea>
</td>
</tr>
<tr>
<td>
<textarea rows="8" cols="80" placeholder="输入审批权限描述信息" style="width: 500px;" name="approver_Rights_Description" id="approver_Rights_Description"></textarea>
</td>
</tr>
<tr>
<td style="text-align: center;">
<button type="submit" onclick="save();">保存</button>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
备注:我就是随便写一下功能,只要知道是这么个意思就好了。(毕竟我只是个酱油前端)
Controller
package com.hnu.scw.controller;
import com.hnu.scw.pojo.Approver;
import com.hnu.scw.service.impl.ApproverImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @ Author :scw
* @ Date :Created in 下午 3:08 2019/4/28 0028
* @ Description:${description}
* @ Modified By:
* @Version: $version$
*/
@Controller
public class ApproverController {
@Autowired
private ApproverImpl approverImpl;
/**
* 跳转到添加审批人员的界面
* @return
*/
@RequestMapping(value = "/showapprover")
public String showApproverPage(){
return "user_toapprover";
}
/**
* 添加审批人员的信息
* @return 返回添加成功的页面
*/
@RequestMapping(value = "/addapprover")
public String addApprover(Approver approver){
approverImpl.saveApproverUser(approver);
return "success";
}
}
备注:这个很简单,我就是演示添加审批人员的操作和跳转到添加页面。。像其他的删改查这样的功能,我觉得没什么好多说的。
Service
package com.hnu.scw.service.impl;
import com.hnu.scw.mapper.ApproverMapper;
import com.hnu.scw.pojo.Approver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ Author :scw
* @ Date :Created in 下午 3:19 2018/6/15 0015
* @ Description:处理审批人员的操作
* @ Modified By:
* @Version: $version$
*/
@Service
public class ApproverImpl {
@Autowired
private ApproverMapper approverMapper;
/**
* 添加用户为审批人
* @param approver
*/
public void saveApproverUser(Approver approver) {
approverMapper.saveApprover(approver);
}
}
备注:我这里为了偷懒就直接写Service的实现类了哈,就不写多余的接口类了。。在正式开发的时候,建议还是采用接口实现类的方式哈。。。
Mapper
package com.hnu.scw.mapper;
import com.hnu.scw.pojo.Approver;
import java.util.List;
/**
* @ Author :scw
* @ Date :Created in 下午 3:21 2018/6/15 0015
* @ Description:对应于审批的mapper操作接口
* @ Modified By:
* @Version: $version$
*/
public interface ApproverMapper {
/**
* 添加一个审批人员实体
* @param approver
*/
void saveApprover(Approver approver);
}
MapperXml
<?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">
<!-- 写Sql语句 -->
<mapper namespace="com.hnu.scw.mapper.ApproverMapper">
<!-- 添加一个审批人员数据-->
<insert id="saveApprover" parameterType="com.hnu.scw.pojo.Approver">
INSERT INTO sys_approver(user_Id, approver_Description,approver_Rights_Description,user_Name)
VALUES (
#{user_Id},
#{approver_Description},
#{approver_Rights_Description},
#{user_Name}
)
</insert>
</mapper>
总结:上面的就是从前端到后台的一整个流程,当然这只是比较简单的处理,而更详细的处理还是需要你自己去不断的完善(比如,判空和数据校验这些内容)。
- 添加审批节点
界面效果:
JSP:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>审批节点</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/css/bootstrap.min.css" charset="utf-8"/>
<!-- 引入 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/bootstrap.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/chosen.jquery.min.js"></script>
<!-- 设置表格居中 -->
<style type="text/css">
#table_report thead tr th{
text-align: center;
}
#table_report tbody tr td{
text-align: center;
}
</style>
</head>
<body>
<!-- 添加节点的界面 ,默认开始不显示-->
<div id="addNodeInfodiv" class="row-fluid" >
<form action="" method="post" id="submmitapprovnode" name="submmitapprovnode">
<input type="hidden" id="saveapproverid" name="saveapproverid">
<table id="table_report" class=" table-text table table-striped table-bordered table-hover" >
<thead>
<tr>
<th>审批节点名称</th>
<td>
<input type="text" placeholder="审批节点名称" name="node_Name" id="node_Name">
</td>
<th>审批通过最少人数</th>
<td>
<input type="text" placeholder="审批节点需要通过的最少人数" name="node_PassNumber" id="node_PassNumber" onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')">
</td>
<th>审批总人数</th>
<td>
<input type="text" placeholder="审批节点的总审批人数" name="node_TotalNumber" id="node_TotalNumber" onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')" >
</td>
</tr>
<!-- 关于显示审核人员列表内容 -->
<tr>
<th>添加审核人员</th>
<td>
<select id="showapproverpeople" name="showapproverpeople">
<option>选择要添加的人员</option>
<!--我这里演示就先下死的-->
<option value="1">张三</option>
<option value="2">李四</option>
<option value="3">王五</option>
<!--以后就是从审核人员表里面读出对应的数据 -->
</select>
<button type="button" class="btn btn-success" id="addApprover" name="addApprover" onclick="addApproverjs();">添加</button>
</td>
</tr>
<tr>
<th>节点审批人员名单</th>
<td colspan="6" id="approverOrder" style="height: 150px;width: 92%">
</td>
</tr >
<tr>
<th>审批节点描述</th>
<td colspan="6">
<textarea rows="6" cols="30" style="width: 98%" name="node_Description" id="node_Description"></textarea>
</td>
</tr>
<tr>
<th>温馨提示</th>
<td colspan="6">
<textarea rows="1" cols="80" style="width: 98%;font-size:18px;color: red;" placeholder="(1)点击提交后添加到审批节点列表中;(2)点击取消返回节点列表界面" readonly="readonly"></textarea>
</td>
</tr>
<tr>
<td style="text-align:center;" colspan="6">
<button class="btn btn-info" type="button" onClick="submmitcontent()"> <i class="ace-icon fa fa-check bigger-110"></i> 提交 </button>
<button class="btn btn-danger" type="button" onClick="cancelcontent()"> <i class="ace-icon fa fa-check bigger-110"></i> 取消</button>
</td>
</tr>
</thead>
</table>
</form>
</div>
</div>
<script type="text/javascript">
//处理添加审核人员的操作
function addApproverjs(){
//获取下拉列表中选中的内容
var selectvalue = $("#showapproverpeople").val();
var selectshow = $("#showapproverpeople option:checked").text();//获取选中的显示内容
if( selectshow == "选择要添加的人员"){
alert("请选择所要添加的名单哦!!");
}
else{
var ifAddResult = true; //标识是否进行添加操作
//判断选择的人员中是否已经添加过了
$('#approverOrder div').each(function(i , n){
if($(this).attr("id") == selectvalue){
alert("该人员已经在审批人员列表中,请不要重复添加");
ifAddResult = false;
}
});
if(ifAddResult == true){
//获取在审核人员中,已经有多少个人,这样能够方便进行点击取消操作
var numberdiv = $("#approverOrder").children().length;
//将选中的内容添加到审核人员顺序中
var $addcontent = $('<div style="display:inline-block; border:1px #000000 solid;margin: 10px;" id="'+selectvalue+'"><span>'+selectshow+'</span><button class="btn btn-danger btn-sm" type="button" onclick="cancelCurrentPeopel(\''+selectvalue+'\');">取消</button></div>');
//添加到审核人员的td标签中
$addcontent.appendTo($("#approverOrder"));
alert("添加成功!");
}
}
}
//审核人员中的取消审核人员的操作,这样等会以后直接通过userid进行搜索判断td中对应的div的id为这个的就删除就可以了
function cancelCurrentPeopel(userid){
//遍历整个审核人列表的td,找到是点击取消的这个userid的div进行移除
$('#approverOrder div').each(function(i , n){
//判断是否是点击的那个内容的ID,如果是就进行删除
if($(this).attr("id") == userid ){
$(this).remove();
}
});
}
//点击添加审核节点中的提交按钮
function submmitcontent(){
//(1)当点击之后,需要要判断其他的必要填的内容是否已经填写了
//节点名称
if($('#node_Name').val() == "" || $('#node_Name').val() == null){
$("#node_Name").tips({
side:3,
msg:'请输入节点名称',
bg:'#AE81FF',
time:2
});
$("#node_Name").focus();
return false;
}
//通过人数
if($('#node_PassNumber').val() == "" || $('#node_PassNumber').val() == null){
$("#node_PassNumber").tips({
side:3,
msg:'请输入最小通过人数',
bg:'#AE81FF',
time:2
});
$("#node_PassNumber").focus();
return false;
}
//最大人数
if($('#node_TotalNumber').val() == "" || $('#node_TotalNumber').val() == null){
$("#node_TotalNumber").tips({
side:3,
msg:'请输入节点最多人数',
bg:'#AE81FF',
time:2
});
$("#node_TotalNumber").focus();
return false;
}
//节点描述内容
if($('#node_Description').val() == "" || $('#node_Description').val() == null){
$("#node_Description").tips({
side:3,
msg:'请输入节点描述信息',
bg:'#AE81FF',
time:2
});
$("#node_Description").focus();
return false;
}
//判断添加的审核人员列表中的个数是否等于的填入的总的人数大小
if($("#approverOrder").children().length != $('#node_TotalNumber').val()){
$("#node_TotalNumber").tips({
side:3,
msg:'输入的总人数不等于审批列表人员个数',
bg:'#AE81FF',
time:2
});
$("#node_TotalNumber").focus();
return false;
}
//判断是否填入的总的审批人数小于最小通过的人数
if($('#node_TotalNumber').val() < $('#node_PassNumber').val()){
$("#node_PassNumber").tips({
side:3,
msg:'输入的最小通过人员个数大于审批总人数',
bg:'#AE81FF',
time:2
});
$("#node_PassNumber").focus();
return false;
}
//(2)把审核人员的真正序号的名单进行提交
var approverId = "";
//首先遍历审核人员顺序中的div标签的id,因为之前就已经把userid进行封装了
$('#approverOrder div').each(function(i , n){
//alert($(this).attr("id"));
approverId = approverId +"-"+$(this).attr("id"); //通过"-"来进行分割
});
//将得到的审核人员的userid放到form表单中的一个隐藏控制,方便后面进行提交到后台
$('#saveapproverid').val(approverId);
//(3)提交form表单到后台
$('#submmitapprovnode').attr({action:'asystem_saveapprovernode'});
$('#submmitapprovnode').submit();
}
</script>
</body>
</html>
备注:要是想显示实际操作效果,别忘记添加对应的Jquery和Bootstrap的引用文件。
Controller:
package com.hnu.scw.controller;
import com.hnu.scw.pojo.ApproverNode;
import com.hnu.scw.pojo.ApproverNodeOrder;
import com.hnu.scw.service.impl.ApproverNodeImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @ Author :scw
* @ Date :Created in 下午 3:08 2019/4/28 0028
* @ Description:审批节点的管理
* @ Modified By:
* @Version: $version$
*/
@Controller
public class ApproverNodeController {
@Autowired
private ApproverNodeImpl approverNodeImpl;
/**
* 跳转到添加审批节点的界面
* @return
*/
@RequestMapping(value = "/showapprovernode")
public String showApproverPage(){
return "asystem_appnode_list";
}
/**
* 处理添加节点的操作
* @return
* @throws Exception
*/
@RequestMapping(value ="/asystem_saveapprovernode")
public String editApproverNode(String saveapproverid, ApproverNode approverNode) {
//首先得到所有提交过来的userid的内容,因为在jsp之前用"-"进行的分割
String users = saveapproverid;
String[] useridOne = users.split("-");//得到单个的审核人员的ID
//进行插入数据的处理,分别要插入到两张表中,sys_approvnodepeople和sys_approvnode
approverNodeImpl.saveApproNode(approverNode); //插入到审核节点表中
//查询数据库中节点数据的最大ID的数字(因为这样才知道当前的节点ID,方便节点管理表中得到该新增条目的序号)
//这个还可以在插入的时候在Mybatis进行直接返回那条数据的ID,我这里主要是为了让大家知道有这个个处理,所以特意进行分开处理的。
Integer number = approverNodeImpl.findNumberNode();
//循环遍历插入(下标从1开始,因为分割后第一个是为空的,之前这样处理了)
for(int i =1 ; i <useridOne.length ; i++){
ApproverNodeOrder approverNodeOrder = new ApproverNodeOrder();
approverNodeOrder.setApprovnode_nodeId(number);
approverNodeOrder.setApprovnode_UserId(useridOne[i]);
approverNodeOrder.setApprovnode_Order(i);
//插入数据到审核节点对应的顺序表中
approverNodeImpl.saveApproNodeToPeople(approverNodeOrder);
}
return "success";
}
}
备注:就对添加处理进行处理。
Service:
package com.hnu.scw.service.impl;
import com.hnu.scw.mapper.ApproverNodeMapper;
import com.hnu.scw.pojo.ApproverNode;
import com.hnu.scw.pojo.ApproverNodeOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ Author :scw
* @ Date :Created in 下午 3:19 2018/6/15 0015
* @ Description:处理审批节点的操作
* @ Modified By:
* @Version: $version$
*/
@Service
public class ApproverNodeImpl {
@Autowired
private ApproverNodeMapper approverNodeMapper;
/**
* 添加审批节点
* @param approverNode
*/
public void saveApproNode(ApproverNode approverNode) {
approverNodeMapper.saveapprovnode(approverNode);
}
/**
* 查询节点表中一共有多少条数据,
* @throws Exception
* @return:返回最大的序号
*/
public Integer findNumberNode(){
return approverNodeMapper.findNumberNode();
}
/**
* 添加审批节点顺序的管理
* @param approverNodeOrder
*/
public void saveApproNodeToPeople(ApproverNodeOrder approverNodeOrder){
approverNodeMapper.saveApproNodeToPeople(approverNodeOrder);
}
}
Mapper:
package com.hnu.scw.mapper;
import com.hnu.scw.pojo.ApproverNode;
import com.hnu.scw.pojo.ApproverNodeOrder;
/**
* @ Author :scw
* @ Date :Created in 下午 3:21 2018/6/15 0015
* @ Description:对应于审批节点的mapper操作接口
* @ Modified By:
* @Version: $version$
*/
public interface ApproverNodeMapper {
/**
* 添加一个审批节点实体
* @param approverNode
*/
void saveapprovnode(ApproverNode approverNode);
Integer findNumberNode ();
void saveApproNodeToPeople(ApproverNodeOrder approverNodeOrder);
}
MapperXml:
<?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">
<!-- 写Sql语句 -->
<mapper namespace="com.hnu.scw.mapper.ApproverNodeMapper">
<!-- 插入数据到审核节点表中 -->
<insert id="saveapprovnode" parameterType="com.hnu.scw.pojo.ApproverNode" >
insert into
sys_approvnode(
node_Name,
node_PassNumber,
node_Description,
node_TotalNumber
)
values(
#{node_Name},
#{node_PassNumber},
#{node_Description},
#{node_TotalNumber}
)
</insert>
<!-- 查询返回审核表中的条目数 -->
<select id="findNumberNode" resultType="Integer">
select max(node_Id)
from
sys_approvnode
</select>
<!-- 插入数据到节点管理员中 -->
<insert id="saveApproNodeToPeople" parameterType="com.hnu.scw.pojo.ApproverNodeOrder">
insert into
sys_approvnodepeople(
approvnode_UserId,
approvnode_nodeId
)values(
#{approvnode_UserId},
#{approvnode_nodeId}
)
</insert>
</mapper>
- 添加审批流程
界面效果:
JSP:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
<base href="<%=basePath%>">
</head>
<body>
<div class="container-fluid" id="main-container">
<div id="page-content" class="clearfix">
<div class="row-fluid">
<div class="row-fluid">
<form action="" method="post" name="processaddform" id="processaddform">
<!-- 用个隐藏的input保存添加了多少个审批节点 -->
<input type="hidden" value="1" name="savenodenumber" id="savenodenumber">
<!--用于隐藏所有的审批节点的id值,通过符号“逗号”分割-->
<input type="hidden" value="" name="allnodeselecteids" id="allnodeselecteids">
<!--用于隐藏所有的审批节点的是否可以返回的值,通过符号“逗号”分割-->
<input type="hidden" value="" name="allnodeselectechecks" id="allnodeselectechecks">
<table cellspacing="120">
<tr>
<td>
<div class="col-xs-6">
<h4 class="lighter">
<i class="icon-hand-right icon-animated-hand-pointer blue"></i>
<a data-toggle="modal" class="blue">流程名称</a>
</h4>
<input name="process_Name" id="process_Name" type="text" id="inputInfo" class="width-40" placeholder="请输入流程名称"/>
</div>
</td>
<td>
<div class="col-xs-6">
<h4 class="lighter">
<i class="icon-hand-right icon-animated-hand-pointer blue"></i>
<a data-toggle="modal" class="blue">流程类型 </a>
</h4>
<select id="process_Type" name="process_Type">
<option value="审批流程">审批流程</option>
<option value="工作流程">工作流程</option>
</select>
</div>
</td>
</tr>
<tr>
<td>
<h4 class="lighter">
<i class="icon-hand-right icon-animated-hand-pointer blue"></i>
<a data-toggle="modal" class="blue">流程内容 </a>
</h4>
</td>
</tr>
</table>
<textarea name="process_Content" id="process_Content" rows="4" cols="" style="width: 100%" placeholder="请输入审批流程内容" title="审批流程内容"></textarea>
<hr/>
<!-- 关于审批流程中节点管理 -->
<h4 class="lighter">
<i class="icon-hand-right icon-animated-hand-pointer blue"></i>
<a data-toggle="modal" class="blue">流程详情 </a>
<div style="float: right;">
<button class="btn btn-danger" type="button" onClick="clearProcessDetail();">清空详情</button>
</div>
</h4>
<table id="processnodedetail"
class="text-table table table-striped table-bordered table-hover">
<!-- 开始循环 -->
<thead>
<tr>
<th>审批顺序</th>
<th>审批节点</th>
<th>是否可回退</th>
<th>审批操作</th>
</tr>
</thead>
<tbody id="addprocessnode">
<tr>
<td>
1
</td>
<!-- 循环产生审批节点的信息 -->
<td>
<select id="processdetail_NodeId0" name="processdetail_NodeId0" >
<c:forEach var="nodeinfo" items="${nodeinfo}">
<option value="${nodeinfo.node_Id}">${nodeinfo.node_Name}</option>
</c:forEach>
</select>
</td>
<td>
<label class="col-sm-0" style="text-align:center">
<!-- 标识是否可以被打回 -->
<input id="processdetail_Back0" name="processdetail_Back0" checked="checked" type="checkbox"
class="ace ace-switch ace-switch-5">
<span class="lbl middle"></span>
</label>
</td>
<!-- 对于审批详情节点中操作 -->
<td style="text-align: center;" name="nodeoption" id="nodeoption" >
<!-- 上移 -->
<a name="upbtn0" id="upbtn0" class="btn btn-mini btn-info" onclick="upNode(0);" title="上移" style="margin-right: 20px;"><i class="icon-arrow-up" ></i></a>
<!-- 下移 -->
<a name="downbtn0" id="downbtn0" class="btn btn-mini btn-info" onclick="downNode(0);" title="下移" style="margin-rigth: 20px;"><i class="icon-arrow-down" ></i></a>
<!-- 删除 -->
<a name="delebtn0" id="delebtn0" class="btn btn-mini btn-danger" onclick="deleteNodeSimple(0);" title="删除" style="margin-left: 20px;"><i class="icon-trash"></i></a>
</td>
</tr>
</tbody>
</table>
</form>
<!-- 底部操作按钮 -->
<div class="page-header position-relative">
<table style="width: 100%;">
<tbody>
<tr>
<td>
<button class="btn btn-success" type="button"
onClick="addProcessNode();">
<i class="ace-icon fa fa-check bigger-110"></i> 增加步骤
</button>
<button class="btn btn-info" type="button"
onClick="submmitContent();">
<i class="ace-icon fa fa-check bigger-110"></i> 提交设置
</button>
<button class="btn btn-warning" type="button"
onClick="backToShow();">
<i class="ace-icon fa fa-check bigger-110"></i> 返回显示界面
</button>
</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 引入 -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/css/bootstrap.min.css" charset="utf-8"/>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-1.5.1.min.js"></script>
<script src="${pageContext.request.contextPath}/static/js/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/static/js/ace-elements.min.js"></script>
<script src="${pageContext.request.contextPath}/static/js/ace.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/chosen.jquery.min.js"></script>
<!-- 下拉框 -->
<script type="text/javascript"
src="${pageContext.request.contextPath}/static/js/bootstrap-datepicker.min.js"></script>
<!-- 日期框 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/bootbox.min.js"></script>
<!-- 确认窗口 -->
<!-- 引入 -->
<!-- wizard-->
<link rel="stylesheet" href="${pageContext.request.contextPath}/static/css/wizard_ace.min.css" />
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery.tips.js"></script>
<!-- 处理添加审批流程的js操作 -->
<script type="text/javascript">
//处理添加流程节点的操作
function addProcessNode(){
//(1)首先获取已经有多少给步骤,即获取tbody中的tr的长度
var leng = $("#addprocessnode").children().length;
var $addnode = $('<tr>'+
'<td>'+(leng+1)+'</td><td>'+
'<select id="processdetail_NodeId'+leng+'" name="processdetail_NodeId'+leng+'">'+
'<c:forEach var="nodeinfo" items="${nodeinfo}">'+
'<option value="${nodeinfo.node_Id}">${nodeinfo.node_Name}</option>'+
'</c:forEach>'+
'</select>'+
'</td>'+
'<td>'+
'<label class="col-sm-0" style="text-align: center">'+
'<input name="processdetail_Back'+leng+'" id="processdetail_Back'+leng+'" checked="checked" type="checkbox"'+
'class="ace ace-switch ace-switch-5">'+
'<span class="lbl middle"></span>'+
'</label>'+
'</td >'+
'<td style="text-align: center;">'+
'<a name="downbtn'+leng+'" id="downbtn'+leng+'" class="btn btn-mini btn-info" onclick="upNode('+(leng)+');" title="上移" style="margin-right: 20px;"><i class="icon-arrow-up" ></i></a>'+
'<a name="downbtn'+leng+'" id="downbtn'+leng+'" class="btn btn-mini btn-info" onclick="downNode('+(leng)+');" title="下移" style="margin-rigth: 20px;"><i class="icon-arrow-down" ></i></a>'+
'<a name="delebtn'+leng+'" id="delebtn'+leng+'" class="btn btn-mini btn-danger" onclick="deleteNodeSimple('+(leng)+');" title="删除" style="margin-left: 20px;"><i class="icon-trash"></i></a>'+
'</td>'+
'</tr>');
$addnode.appendTo($("#addprocessnode"));
alert("添加成功!");
}
//处理提交流程的操作
function submmitContent(){
//(1)先判断是否填入的信息符合规范
//流程名称
if($('#process_Name').val() == "" || $('#process_Name').val() == null){
$("#process_Name").tips({
side:3,
msg:'请输入流程名称',
bg:'#AE81FF',
time:2
});
$("#process_Name").focus();
return false;
}
//流程内容
if($('#process_Content').val() == "" || $('#process_Content').val() == null){
$("#process_Content").tips({
side:3,
msg:'请输入流程内容',
bg:'#AE81FF',
time:2
});
$("#process_Content").focus();
return false;
}
//判断添加的审批节点是否存在重复的节点(便利判断option中的value是否存在一样)
var repeatSuccess = false;
//获取每个下拉列表选中的值
$('#addprocessnode tr').each(function(key1 , value){
var currentValue = $(this).children("td").children("select").val();
$('#addprocessnode tr').each(function(key2 , value){
if(key1 != key2){
var nextValue = $(this).children("td").children("select").val();
if(currentValue == nextValue){
alert("审批节点中:["+(key1+1)+"]与["+(key2+1)+"]重复,请确认!");
repeatSuccess = true;
return false;
}
}
});
//跳出循环
if(repeatSuccess){
return false;
}
});
//返回整个判断程序
if(repeatSuccess){
return false;
}
//(2)上面的判断都符合后,进行页面跳转
//要获得审批节点中的个数,就是tr的条数,方便后台进行遍历搜索的次数
var number = $("#addprocessnode").children().length;
$('#savenodenumber').val(number);
//(3)获得所有要添加的节点的id和是否可以被退回
var nodeIdResult = "";
var nodeCheckResult = "";
for(var i=0; i<number; i++){
//如果是最后一个就不需要多添加额外的"分割符合"
if(i == (number - 1)){
nodeIdResult = nodeIdResult + $('#processdetail_NodeId'+i).val()
nodeCheckResult = nodeCheckResult + $('#processdetail_Back'+i).is(':checked')
}else{
nodeIdResult = nodeIdResult + $('#processdetail_NodeId'+i).val() + ","
nodeCheckResult = nodeCheckResult + $('#processdetail_Back'+i).is(':checked') + ','
}
}
$('#allnodeselecteids').val(nodeIdResult)
$('#allnodeselectechecks').val(nodeCheckResult)
$('#processaddform').attr({action:'/asystem_editprocessdetail'});
$('#processaddform').submit();
}
//处理清除流程节点的操作
function clearProcessDetail(){
$("#addprocessnode").children().remove();
}
//处理上移按钮的操作,参数clickindex为点击的是第几个,从0开始
function upNode(clickindex){
//(1)如果点击的位置是0,那么就不能再上移
if(clickindex == 0){
alert("已经在第一个,不能再上移了哦!");
}
//(2)非第一个的情况
else{
//(3)改变上下两个位置的所有信息内容
//获取到当前点击行的所有信息
var currentNodeId = $('#processdetail_NodeId'+clickindex).val();
var currentNodeName = $('#processdetail_NodeId'+clickindex +' option:checked').text();
var currentNodeBack = $('#processdetail_Back'+clickindex).attr("checked");
//获取点击行对应的上一行的所有信息,获取上一行的索引
lastindex = parseInt(clickindex) -1;
var lastNodeId = $('#processdetail_NodeId'+(lastindex)).val();
var lastNodeName = $('#processdetail_NodeId'+(lastindex) +' option:checked').text();
var lastNodeBack = $('#processdetail_Back'+(lastindex)).attr("checked");
//(4)交换当前行和上一行中标签对应的ID属性和Name属性的值
//修改当前节点的内容,其实就是交换当前行和上一行的数据内容
$('#processdetail_NodeId'+clickindex).val(lastNodeId);
$('#processdetail_NodeId'+clickindex +' option:checked').text(lastNodeName);
//如果点击节点上面的是点击Yes状态,那么就进行相应的修改即可
if(lastNodeBack == "checked"){
$('#processdetail_Back'+clickindex).attr({"checked":"checked"});
}
else{
$('#processdetail_Back'+clickindex).removeAttr("checked");
}
//修改上一个节点的内容,其实就是交换当前行和上一行的数据内容
$('#processdetail_NodeId'+(lastindex)).val(currentNodeId);
$('#processdetail_NodeId'+(lastindex) +' option:checked').text(currentNodeName);
if(currentNodeBack == "checked"){
$('#processdetail_Back'+(lastindex)).attr({"checked":"checked"});
}
else{
$('#processdetail_Back'+(lastindex)).removeAttr("checked");
}
}
}
//处理下移按钮的操作,参数clickindex为点击的是第几个,从0开始
function downNode(clickindex){
//(1)首先判断是否是点击的最后一个,如果是,那么就无法再进行下移操作
//拿到一共有多少条数据
var leng = $("#addprocessnode").children().length;
if((leng-1) == clickindex){ //-1判断是因为后面的是从0开始算
alert("已经是最后一个,无法再进行下移哦");
}
//(2)非最后一个,再进行后面的操作,这个同上移的内容是一样的
else{
//获取到当前点击行的所有信息
var currentNodeId = $('#processdetail_NodeId'+clickindex).val();
var currentNodeName = $('#processdetail_NodeId'+clickindex +' option:checked').text();
var currentNodeBack = $('#processdetail_Back'+clickindex).attr("checked");
//获取点击行对应的下一行的所有信息,要进行转型才能加减
var nextindex = parseInt(clickindex) +1;
var lastNodeId = $('#processdetail_NodeId'+(nextindex)).val();
var lastNodeName = $('#processdetail_NodeId'+(nextindex) +' option:checked').text();
var lastNodeBack = $('#processdetail_Back'+(nextindex)).attr("checked");
//(4)交换当前行和下一行中标签对应的ID属性和Name属性的值
//修改当前节点的内容,其实就是交换当前行和下一行的数据内容
$('#processdetail_NodeId'+clickindex).val(lastNodeId);
$('#processdetail_NodeId'+clickindex +' option:checked').text(lastNodeName);
//如果点击节点上面的是点击Yes状态,那么就进行相应的修改即可
if(lastNodeBack == "checked"){
$('#processdetail_Back'+clickindex).attr({"checked":"checked"});
}
else{
$('#processdetail_Back'+clickindex).removeAttr("checked");
}
//修改下一个节点的内容,其实就是交换当前行和下一行的数据内容
$('#processdetail_NodeId'+(nextindex)).val(currentNodeId);
$('#processdetail_NodeId'+(nextindex) +' option:checked').text(currentNodeName);
if(currentNodeBack == "checked"){
$('#processdetail_Back'+(nextindex)).attr({"checked":"checked"});
}
else{
$('#processdetail_Back'+(nextindex)).removeAttr("checked");
}
}
}
//处理删除单个审批节点的操作,参数clickindex为点击的是第几个,从0开始
function deleteNodeSimple(clickindex){
//弹出一个确认框
if(confirm("确认要删除该条审批信息吗?")){
//(1)获取已经存在的条数
var number = $('#addprocessnode').children().length;
//(2)删除点击的那行的数据
/* $('#addprocessnode tr').eq(clickindex).remove(); */
//(3)将删除索引后面的信息进行移动交换(其实就是后面的把前面的进行覆盖)
var currentNodeId = "";
var currentNodeName="";
var currentNodeBack="";
clickindex = parseInt(clickindex); //将字符串型的clickindex转为int
for(var i = clickindex + 1 ; i < number ; i++ ){ //这里将i=clickindex+1进行处理,是因为想获取后面的内容,再来覆盖前面的内容
//获取到当前行的所有信息
currentNodeId = $('#processdetail_NodeId'+i).val();
currentNodeName = $('#processdetail_NodeId'+i +' option:checked').text();
currentNodeBack = $('#processdetail_Back'+i).attr("checked");
//将前面的数据进行依次覆盖
$('#processdetail_NodeId'+(i-1)).val(currentNodeId); //这里-1是因为,在for的时候首先+1了,那么减一才代表上一个
$('#processdetail_NodeId'+(i-1) +' option:checked').text(currentNodeName);
if( currentNodeBack =="checked"){
$('#processdetail_Back'+(i-1)).attr("checked");
}
else{
$('#processdetail_Back'+(i-1)).removeAttr("checked");
}
}
//删除最后一行的数据就可以了(因为我是通过后者一直覆盖)
$('#addprocessnode tr').eq((number-1)).remove();
}
}
</script>
</body>
</html>
Controller:
package com.hnu.scw.controller;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ApprovalProcessDetail;
import com.hnu.scw.pojo.ApproverNode;
import com.hnu.scw.pojo.ApproverNodeOrder;
import com.hnu.scw.service.impl.ApprovalProcessImpl;
import com.hnu.scw.service.impl.ApproverNodeImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.List;
/**
* @ Author :scw
* @ Date :Created in 下午 3:08 2019/4/28 0028
* @ Description:审批流程的管理
* @ Modified By:
* @Version: $version$
*/
@Controller
public class ApproverProcessController {
@Autowired
private ApprovalProcessImpl approvalProcessImpl;
/**
* 跳转到添加审批流程的界面
* @return
*/
@RequestMapping(value = "/showapproverprocess")
public ModelAndView showApproverPage(){
ModelAndView mav = new ModelAndView();
List<ApproverNode> list = new ArrayList<ApproverNode>();
//这里模拟一下已经存在了N个审批节点的数据(实际开发中就去读审批节点表即可)
ApproverNode approverNode = new ApproverNode();
approverNode.setNode_Id(1);
approverNode.setNode_Name("我是小白节点");
ApproverNode approverNode1 = new ApproverNode();
approverNode1.setNode_Id(2);
approverNode1.setNode_Name("我是小红节点");
ApproverNode approverNode2 = new ApproverNode();
approverNode2.setNode_Id(3);
approverNode2.setNode_Name("我是小黑节点");
list.add(approverNode);
list.add(approverNode1);
list.add(approverNode2);
//返回所有的审核节点的信息
mav.addObject("nodeinfo" ,list) ;
mav.setViewName("asystem_approvalprocess_add");
return mav;
}
/**
* 处理添加审批流程的数据
* @return
* @throws Exception
*/
@RequestMapping( value ="/asystem_editprocessdetail")
public String editProvessDedail(String allnodeselecteids, String allnodeselectechecks, String savenodenumber, ApprovalProcess approvalProcess, ApprovalProcessDetail approvalProcessDetail) throws Exception{
//(1)将流程数据进行插入到数据库中
approvalProcessImpl.saveProcessInfoData(approvalProcess);
//(2)查询得到审批流程表中最大的流程ID号,从而得到该增加的审批节点对应的审批流程ID
Integer totalProcessNumber = approvalProcessImpl.findTotalNumber();
//(3)得到一共添加的审批节点个数,这样就能够得到每个节点的顺序
int nodeNumber = Integer.parseInt(savenodenumber);
//(4)循环遍历每个节点的信息,然后插入到审批流程详细数据表中
ApprovalProcessDetail aapd = new ApprovalProcessDetail();
//(5)获取所有的节点的ID和是否能够被退回的信息
String[] splitIds = allnodeselecteids.split(",");
String[] splitChecks = allnodeselectechecks.split(",");
for (int i = 0 ; i <nodeNumber ;i++){
aapd.setProcessdetail_Id(totalProcessNumber); //设置节点对应的审批流程ID,其实就是总条数
aapd.setProcessdetail_NodeId(Integer.parseInt(splitIds[i]));//设置节点ID
aapd.setProcessdetail_Back(splitChecks[i]); //设置是否该节点可以返回,true就是可以,false就是不行
aapd.setProcessdetail_Nodeorder(i+1); //设置节点处理顺序,因为从0开始,但是数据库设置为1开始,所以要+1
//插入数据到数据库
approvalProcessImpl.saveApprovalNode(aapd);
}
//处理完后返回到显示所有流程界面
return "success";
}
}
Service:
package com.hnu.scw.service.impl;
import com.hnu.scw.mapper.ApprovalProcessMapper;
import com.hnu.scw.mapper.ApproverNodeMapper;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ApprovalProcessDetail;
import com.hnu.scw.pojo.ApproverNode;
import com.hnu.scw.pojo.ApproverNodeOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ Author :scw
* @ Date :Created in 下午 3:19 2018/6/15 0015
* @ Description:处理审批流程的操作
* @ Modified By:
* @Version: $version$
*/
@Service
public class ApprovalProcessImpl {
@Autowired
private ApprovalProcessMapper approvalProcessMapper;
/**
* 添加审批节点
* @param approvalProcess
*/
public void saveProcessInfoData(ApprovalProcess approvalProcess) {
approvalProcessMapper.saveProcessInfoData(approvalProcess);
}
/**
* 查询流程表中一共有多少条数据,
* @throws Exception
* @return:返回最大的序号
*/
public Integer findTotalNumber(){
return approvalProcessMapper.findTotalNumber();
}
/**
* 添加审批节点的管理
* @param approvalProcessDetail
*/
public void saveApprovalNode(ApprovalProcessDetail approvalProcessDetail){
approvalProcessMapper.saveApprovalNode(approvalProcessDetail);
}
}
Mapper:
package com.hnu.scw.mapper;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ApprovalProcessDetail;
import com.hnu.scw.pojo.ApproverNode;
import com.hnu.scw.pojo.ApproverNodeOrder;
/**
* @ Author :scw
* @ Date :Created in 下午 3:21 2018/6/15 0015
* @ Description:对应于审批流程的mapper操作接口
* @ Modified By:
* @Version: $version$
*/
public interface ApprovalProcessMapper {
/**
* 添加一个审批流程实体
* @param approvalProcess
*/
public void saveProcessInfoData(ApprovalProcess approvalProcess);
Integer findTotalNumber();
/**
* 添加对应审批流程的审批节点的详细信息
* @param approvalProcessDetail
*/
void saveApprovalNode(ApprovalProcessDetail approvalProcessDetail);
}
MapperXml:
<?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">
<!-- 写Sql语句 -->
<mapper namespace="com.hnu.scw.mapper.ApprovalProcessMapper">
<!-- 插入新增的流程数据 -->
<insert id="saveProcessInfoData" parameterType="com.hnu.scw.pojo.ApprovalProcess">
insert into
sys_process_approval(
process_Name,
process_Content,
process_Type
)values(
#{process_Name},
#{process_Content},
#{process_Type}
)
</insert>
<!-- 查询一共有多少条审批流程 -->
<select id="findTotalNumber" resultType="Integer">
select max(process_Id)
from
sys_process_approval
</select>
<!-- 插入数据到流程详细表中 -->
<insert id="saveApprovalNode" parameterType="com.hnu.scw.pojo.ApprovalProcessDetail">
insert into
sys_process_detail(
processdetail_Id,
processdetail_NodeId,
processdetail_Nodeorder,
processdetail_Back
)values(
#{processdetail_Id},
#{processdetail_NodeId},
#{processdetail_Nodeorder},
#{processdetail_Back}
)
</insert>
</mapper>
备注:上面的代码就完成了对审批流的基础操作的处理,那么当我们需要真正使用审批流处理,接下来又该如何进行处理呢?
我接下来用“日常请假”的一个例子来为大家进行简单的演示。
当知道“日常审批”如何处理,那么对于其他类似的审批操作也就是类似即可。
5. 日常请假流程处理
创建表:
备注:我这里就简单的以几个字段表明就好了,更为详细的内容就自己根据需要进行添加即可。
界面效果:
JSP:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
<base href="<%=basePath%>">
<meta charset="utf-8" />
<title></title>
<meta name="description" content="overview & stats" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 引入 -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/css/bootstrap.min.css" charset="utf-8"/>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-1.5.1.min.js"></script>
<script src="${pageContext.request.contextPath}/static/js/bootstrap.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery.tips.js"></script>
<!-- 内容居中显示 -->
<style type="text/css">
.mytable tr td {
text-align: center;
}
.mytable tr td label {
text-align: center;
}
.mytable tr td input {
text-align: center;
}
</style>
<script type="text/javascript">
$(top.hangge());
$(document).ready(function(){
if($("#user_id").val()!=""){
$("#loginname").attr("readonly","readonly");
$("#loginname").css("color","gray");
}
});
//保存
function save(){
if($("#abandon_reason").val()==""){
$("#abandon_reason").tips({
side:3,
msg:'请输入请假原因',
bg:'#AE81FF',
time:2
});
$("#abandon_reason").focus();
return false;
}
else{
//获取下拉列表中的所选择的流程的名字
var id = $('#abandon_approve option:selected').attr("id");
$("#process_ApprovalId").val(id);
$("#editAbandonForm").submit();
$("#zhongxin").hide();
$("#zhongxin2").show();
}
}
/**
* 取消按钮
*/
function clickcancel() {
alert("自己去实现把")
}
</script>
</head>
<body>
<form action="/save_abandon" name="editAbandonForm" id="editAbandonForm" method="post">
<!-- 隐藏审批流程的ID -->
<input type="hidden" id="process_ApprovalId" name ="process_ApprovalId">
<!--当前项目的类型-->
<input type="hidden" id="process_Type" name ="process_Type" value="日常请假">
<div id="zhongxin" style="margin-left: 10px;margin-right: 10px;margin-top: 15px;">
<table id="table_report"
class="text-table table table-striped table-bordered table-hover">
<tbody class="mytable">
<!-- 开始循环 -->
<tr>
<td style="text-align: center;" colspan="6"><label><b style="color: red"><h2>新增日常请假表</h2></b></label></td>
</tr>
<td><label>请假项目名<b style="color: red">*</b></label></td>
<td><input type="text" name="project_Name" id="project_Name" placeholder="请输入报废项目名">
<td><label>请假原因<b style="color: red">*</b></label></td>
<td><input type="text" name="abandon_reason" id="abandon_reason" placeholder="请输入报废原因">
</td>
</td>
<td><label>请假审批<b style="color: red">*</b></label></td>
<td>
<select class="chzn-select" name="abandon_approve" id="abandon_approve" data-placeholder="请选择审批流程" style="width: 221px;vertical-align: center">
<c:forEach items="${approvalProcess}" var="info" >
<option id=${info.process_Id }>${info.process_Name}</option>
</c:forEach>
</select>
</td>
</tr>
<tr style="height: 40">
<td style="text-align: center;" colspan="7">
<a class="btn btn-primary" onclick="save();">提交</a>
<a class="btn btn-danger" onclick="clickcancel();">取消</a>
</td>
</tr>
</tbody>
</table>
</div>
</form>
</body>
</html>
实体类(1):
package com.hnu.scw.pojo;
/**
* 日常请假的实体类
*/
public class AssetAbandonManage implements java.io.Serializable{
private Integer id;
//是什么类型的项目(我这里自然就是日常请假了,如果还有财务审批,那么就是财务审批)
private String process_Type;
//请假的主题
private String project_Name;
//请假的原因
private String abandon_reason;
//审批流程的名字
private String abandon_approve;
//审批状态,默认是已提交
private String approve_status = "已提交";
public String getProject_Name() {
return project_Name;
}
public void setProject_Name(String project_Name) {
this.project_Name = project_Name;
}
public String getProcess_Type() {
return process_Type;
}
public void setProcess_Type(String process_Type) {
this.process_Type = process_Type;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAbandon_reason() {
return abandon_reason;
}
public void setAbandon_reason(String abandon_reason) {
this.abandon_reason = abandon_reason;
}
public String getAbandon_approve() {
return abandon_approve;
}
public void setAbandon_approve(String abandon_approve) {
this.abandon_approve = abandon_approve;
}
public String getApprove_status() {
return approve_status;
}
public void setApprove_status(String approve_status) {
this.approve_status = approve_status;
}
}
实体类(2):
package com.hnu.scw.pojo;
/**
*
* @author scw
*2017-09-21
*function:项目流程的实体类,对应数据库中的aproject_process
*/
public class ProjectProcess {
private Integer projectprocess_Id; //项目流程表中ID
private Integer project_Id ; //项目ID
private String project_Name; //项目的审批内容主题
private String project_Stryle = "需要"; //项目是否需要审批,默认需要审批
private Integer current_NodeOrder; //当前审批节点的序号,标识是在第几个审批节点中
private String process_FinishStatus ; //当前项目流程是否完成
private Integer process_ApprovalId ; //选择的审批流程的ID
private String process_ApprovalName ; //审批流程的名字
private String current_NodeName ; //当前审批节点的名称
private Integer description_Passnumber ; //当前审批节点通过的人数
private Integer description_Refusenumber ; //当前审批节点拒绝通过的人数
private String process_Type; //需要进行审批流程处理的审批类型,比如采购,报废,维修
public String getProject_Name() {
return project_Name;
}
public void setProject_Name(String project_Name) {
this.project_Name = project_Name;
}
public String getProcess_Type() {
return process_Type;
}
public void setProcess_Type(String process_Type) {
this.process_Type = process_Type;
}
public Integer getDescription_Refusenumber() {
return description_Refusenumber;
}
public void setDescription_Refusenumber(Integer description_Refusenumber) {
this.description_Refusenumber = description_Refusenumber;
}
public Integer getDescription_Passnumber() {
return description_Passnumber;
}
public void setDescription_Passnumber(Integer description_Passnumber) {
this.description_Passnumber = description_Passnumber;
}
public Integer getProjectprocess_Id() {
return projectprocess_Id;
}
public void setProjectprocess_Id(Integer projectprocess_Id) {
this.projectprocess_Id = projectprocess_Id;
}
public Integer getProject_Id() {
return project_Id;
}
public void setProject_Id(Integer project_Id) {
this.project_Id = project_Id;
}
public String getProject_Stryle() {
return project_Stryle;
}
public void setProject_Stryle(String project_Stryle) {
this.project_Stryle = project_Stryle;
}
public Integer getCurrent_NodeOrder() {
return current_NodeOrder;
}
public void setCurrent_NodeOrder(Integer current_NodeOrder) {
this.current_NodeOrder = current_NodeOrder;
}
public String getProcess_FinishStatus() {
return process_FinishStatus;
}
public void setProcess_FinishStatus(String process_FinishStatus) {
this.process_FinishStatus = process_FinishStatus;
}
public Integer getProcess_ApprovalId() {
return process_ApprovalId;
}
public void setProcess_ApprovalId(Integer process_ApprovalId) {
this.process_ApprovalId = process_ApprovalId;
}
public String getProcess_ApprovalName() {
return process_ApprovalName;
}
public void setProcess_ApprovalName(String process_ApprovalName) {
this.process_ApprovalName = process_ApprovalName;
}
public String getCurrent_NodeName() {
return current_NodeName;
}
public void setCurrent_NodeName(String current_NodeName) {
this.current_NodeName = current_NodeName;
}
}
Controller:
备注:其实这个Controller是可以分两个的,因为可以把不同审批项目进行分开写,但是我这里因为就是演示一个“日常请假”,所以就把“跳转日常请假的处理”放在了这个页面,所以,如果你们在实际开发中,尽量是分开哦。
就仅仅让这一个Controller处理关于项目审批的就好了,那么跳转到对应项目审批的处理就别再这里面也。
实例:就是把showProjectPage这个方法提取出去。
package com.hnu.scw.controller;
import com.hnu.scw.pojo.*;
import com.hnu.scw.service.impl.ApproverNodeImpl;
import com.hnu.scw.service.impl.AssetAbandonImpl;
import com.hnu.scw.service.impl.ProjectApplyImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @ Author :scw
* @ Date :Created in 下午 3:08 2019/4/28 0028
* @ Description:审批项目使用审批流程的管理
* @ Modified By:
* @Version: $version$
*/
@Controller
public class UseApprovalController {
@Autowired
private AssetAbandonImpl assetAbandon;
@Autowired
private ProjectApplyImpl projectApply;
/**
* 跳转到日常请假需要审批的界面
* @return
*/
@RequestMapping(value = "/showproject")
public ModelAndView showProjectPage(){
ModelAndView mav = new ModelAndView();
//获取审批流程的信息
List<ApprovalProcess> approvalProcess = projectApply.findApproveProcess();
mav.addObject("approvalProcess", approvalProcess);
mav.setViewName("abandontable_add");
return mav;
}
/**
* 处理添加日常请假表(对应数据库中的assetAbandon表)
* @return
* @throws Exception
*/
@RequestMapping(value="/save_abandon")
public String save_abandon(ProjectProcess projectProcess, AssetAbandonManage assetAbandonManage){
//(1)添加请假申请的数据
assetAbandon.saveAssetAbandon(assetAbandonManage);
//(2)添加数据信息到项目审批过程表中
// 获取选取审批流程的ID和名字
String processName = assetAbandonManage.getAbandon_approve();
projectProcess.setProcess_ApprovalName(processName);
// 获取项目申请的id
projectProcess.setProject_Id(assetAbandonManage.getId());
// 需要进行审批项目的项目类型,我这里就用“请假申请”为一个例子,
// 实际中肯定是在前端就已经存在了,不同页面不同
projectProcess.setProcess_Type(assetAbandonManage.getProcess_Type());
// 根据流程ID和顺序,查询对应流程表中的第一个流程节点的ID和名字
Integer processId = projectProcess.getProcess_ApprovalId();
String nodeName = projectApply.findFirstNodeNameByProcessId(processId);
projectProcess.setCurrent_NodeName(nodeName);
projectProcess.setDescription_Passnumber(0);// 通过的人数
projectProcess.setDescription_Refusenumber(0);// 不通过的人数
// 该项目流程的完成状态,开始的状态是未完成
projectProcess.setProcess_FinishStatus( "未完成");
// 刚开始的时候设置的审批节点顺序为第一个,这个不设置也可以,因为数据库中默认了为第一个
projectProcess.setCurrent_NodeOrder(1);
// 设置该项目流程是需要进行审批操作
projectProcess.setProject_Stryle("需要");
// 将数据插入到项目过程表中
projectApply.saveOneProjectProcessInfo(projectProcess);
//----------处理添加审批流程的操作结束----scw--
return "success";
}
}
Service(日常请假):
package com.hnu.scw.service.impl;
import com.hnu.scw.mapper.ApprovalProcessMapper;
import com.hnu.scw.mapper.AssetAbandonMapper;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ApprovalProcessDetail;
import com.hnu.scw.pojo.AssetAbandonManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ Author :scw
* @ Date :Created in 下午 3:19 2018/6/15 0015
* @ Description:日常请假项目的操作
* @ Modified By:
* @Version: $version$
*/
@Service
public class AssetAbandonImpl {
@Autowired
private AssetAbandonMapper assetAbandonMapper;
/**
* 添加资产报废数据
* @param assetAbandonManage
*/
public void saveAssetAbandon(AssetAbandonManage assetAbandonManage) {
assetAbandonMapper.saveAssetAbandon(assetAbandonManage);
}
}
Service(审批项目流程):
package com.hnu.scw.service.impl;
import com.hnu.scw.mapper.ApprovalProjectMapper;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ProjectProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 审批处理相关的代码
* @author scw
*
*/
@Service
public class ProjectApplyImpl {
@Autowired
private ApprovalProjectMapper approvalProjectMapper;
/**
* 查询审批流程 增加项目的时候进行选择
* @return
*/
public List<ApprovalProcess> findApproveProcess() {
return approvalProjectMapper.findList();
}
/**
* 根据审批流程Id获取第一处理的节点名
* @param proceesId
* @return
*/
public String findFirstNodeNameByProcessId(Integer proceesId){
return approvalProjectMapper.findFirstNodeName(proceesId);
}
/**
* 添加一条需要审批的数据到审批项目表中
* @param projectProcess
*/
public void saveOneProjectProcessInfo(ProjectProcess projectProcess){
approvalProjectMapper.saveOneProjectProcessInfo(projectProcess);
}
}
Mapper(日常请假):
package com.hnu.scw.mapper;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ApprovalProcessDetail;
import com.hnu.scw.pojo.AssetAbandonManage;
/**
* @ Author :scw
* @ Date :Created in 下午 3:21 2018/6/15 0015
* @ Description:对应于日常请假的mapper操作接口
* @ Modified By:
* @Version: $version$
*/
public interface AssetAbandonMapper {
/**
* 添加对应日常请假项目的详细信息
* @param assetAbandonManage
*/
void saveAssetAbandon(AssetAbandonManage assetAbandonManage);
}
Mapper(项目审批流程):
package com.hnu.scw.mapper;
import com.hnu.scw.pojo.ApprovalProcess;
import com.hnu.scw.pojo.ApprovalProcessDetail;
import com.hnu.scw.pojo.ProjectProcess;
import java.util.List;
import java.util.Map;
/**
* @ Author :scw
* @ Date :Created in 下午 3:21 2018/6/15 0015
* @ Description:对应于审批项目的mapper操作接口
* @ Modified By:
* @Version: $version$
*/
public interface ApprovalProjectMapper {
/**
* 查询系统的所有审批流程内容
* @return
*/
List<ApprovalProcess> findList();
/**
* 根据流程ID获取第一个审批节点
* @param proceesId
* @return
*/
String findFirstNodeName(Integer proceesId);
/**
* 插入一条项目审批数据到项目审批数据库中
* @param projectProcess
*/
void saveOneProjectProcessInfo(ProjectProcess projectProcess);
}
MapperXml(日常请假):
<?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">
<!-- 写Sql语句 -->
<mapper namespace="com.hnu.scw.mapper.AssetAbandonMapper">
<!-- 插入新增的资产报废数据 -->
<insert id="saveAssetAbandon" parameterType="com.hnu.scw.pojo.AssetAbandonManage" useGeneratedKeys="true" keyProperty="id">
insert into
asset_abandon(
project_Name,
process_Type,
abandon_reason,
abandon_approve,
approve_status
)
values(
#{project_Name},
#{process_Type},
#{abandon_reason},
#{abandon_approve},
"已提交"
)
</insert>
</mapper>
MapperXml(项目审批流程):
<?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">
<!-- 写Sql语句 -->
<mapper namespace="com.hnu.scw.mapper.ApprovalProjectMapper">
<resultMap id="approvalproject" type="com.hnu.scw.pojo.ApprovalProcess">
<id property="process_Id" column="process_Id"/>
<result property="process_Name" column="process_Name"/>
<result property="process_Content" column="process_Content"/>
<result property="process_Type" column="process_Type"/>
</resultMap>
<!--获取系统所有的审批流程信息-->
<select id="findList" resultMap="approvalproject">
select
*
from
sys_process_approval
</select>
<!-- 根据选择的审批流程获取对应的第一个审批节点的名字,主要用来显示的 -->
<select id="findFirstNodeName" parameterType="Integer" resultType="String">
select
sys_approvnode.node_Name
from
sys_approvnode ,sys_process_detail
where
sys_process_detail.processdetail_Id = #{processdetail_Id}
and
sys_process_detail.processdetail_NodeId = sys_approvnode.node_Id
and
sys_process_detail.processdetail_Nodeorder = 1
</select>
<insert id="saveOneProjectProcessInfo" parameterType="com.hnu.scw.pojo.ProjectProcess">
insert into
aproject_process(
project_Name,
project_Id,
project_Stryle,
current_NodeOrder,
process_FinishStatus,
process_ApprovalId,
process_ApprovalName,
current_NodeName,
description_Passnumber,
description_Refusenumber,
process_Type
)values(
#{project_Name},
#{project_Id},
#{project_Stryle},
#{current_NodeOrder},
#{process_FinishStatus},
#{process_ApprovalId},
#{process_ApprovalName},
#{current_NodeName},
#{description_Passnumber},
#{description_Refusenumber},
#{process_Type}
)
</insert>
</mapper>
备注:上面这一段代码就演示了:比如张三需要请假,那么就需要进系统的日常请假的页面进行填写相关的内容,然后在其中选择一个审批流程,这样之后对应审批的人进入系统就可以进行相应的“张三要请假的项目”进行审批。而张三就只能看到流程到第几个人审批和审批是否完成这些信息。
那么,当审批的人登录系统,那么他是如何进行审批操作的呢?
那么,继续往下看!!!
(希望你能理清楚这里面的一系列逻辑,思考好了,才继续看是比较好的!)
6. 查看待审批项目列表
界面效果:
JSP:
命名:project_list.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
</head>
<!-- 设置表格居中 -->
<style type="text/css">
#table_report thead tr th{
text-align: center;
}
#table_report tbody tr td{
text-align: center;
}
</style>
<body>
<div class="container-fluid" id="main-container">
<div id="page-content" class="clearfix">
<div class="row-fluid">
<div class="row-fluid">
<table id="table_report" class="table table-striped table-bordered table-hover" style="margin-top: -12px;">
<thead>
<tr>
<th class="center"><label><input type="checkbox" id="zcheckbox"><span class="lbl"></span></label></th>
<th>序号</th>
<th>审批项目名</th>
<th>审批项目流程名</th>
<th>当前审批节点</th>
<th>审批项目类型</th>
<th>是否审批完成</th>
<th class="center">操作</th>
</tr>
</thead>
<tbody>
<!-- 开始循环 -->
<c:choose>
<c:when test="${not empty listProject}">
<c:forEach items="${listProject}" var="projectitem" varStatus="itemindex">
<tr>
<td class="center" style="width: 30px;">
<label>
<input type="checkbox" name="ids">
<span class="lbl"></span>
</label>
</td>
<td>${itemindex.index+1}</td>
<td>${projectitem.project_Name}</td>
<td>${projectitem.process_ApprovalName}</td>
<td>${projectitem.current_NodeName}</td>
<td>${projectitem.process_Type}</td>
<td style="color: red;">${projectitem.process_FinishStatus}</td>
<td>
<a class="btn btn-mini btn-info" title="审批" onClick="lookCurrentProject('${projectitem.projectprocess_Id}');">
<i class="icon-edit"></i>审批</a>
</td>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr class="main_info">
<td colspan="15" class="center">暂时没有数据</td>
</tr>
</c:otherwise>
</c:choose>
</tbody>
</table>
</form>
</div>
</div>
</div>
</div>
<!-- 引入 -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/css/bootstrap.min.css" charset="utf-8"/>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-1.5.1.min.js"></script>
<script src="${pageContext.request.contextPath}/static/js/bootstrap.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery.tips.js"></script>
<script type="text/javascript">
$(top.hangge());
//当搜索框获取到焦点的时候
$("#retrieve_content").hover(function(){
$("#retrieve_content").tips({
side:3,
msg:'检索列表范围:审批项目名;审批项目流程名;当前审批节点;审批项目类型;是否审批完成',
bg:'#AE81FF',
time:3
});
});
//处理点击审批按钮的操作
function lookCurrentProject(projectId){
window.location = "${pageContext.request.contextPath}/showprojectdetaileprocess?projectprocess_Id="+projectId;
}
//处理姓名检索的功能
function search(){
//提交检索功能
$('#approversearchform').submit();
}
</script>
</body>
</html>
Controller:
命名:UseApprovalController
/**
* 显示所有需要审批的项目
*/
@RequestMapping(value = "/showprojectlist")
public ModelAndView showProjectList() throws Exception {
ModelAndView mav = new ModelAndView();
List<ProjectProcess> listProject = projectApply.findAllProject();
mav.addObject("listProject",listProject);
mav.setViewName("/project_list");
return mav;
}
备注:这个写得比较简单,但是在实际开发中,肯定是需要控制权限的,就比如当前登录的人只能看到自己需要审批的内容,而无法看到别人审批的条目。但是我这里就不进行处理,这个不是工作流相关的知识。
- 当审批流程中的某个审批人登录系统进行项目审批
功能:当审批人员点击待审批的列表中的审批按钮,则会进入该页面。
备注:这个部分是最为逻辑麻烦的地方,而且也是审批处理中最关键的地方。请特别注意。
界面:
JSP:
命名:showcurrentproject
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>项目审批界面</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/static/css/bootstrap.min.css" charset="utf-8"/>
<!-- 引入 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/bootstrap.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/chosen.jquery.min.js"></script>
<style type="text/css">
.project_apply_add td{
vertical-align: middle;
}
</style>
</head>
<body>
<div class="container-fluid" id="main-container">
<form action="" method="post" name="projectprocessform" id="projectprocessform" >
<input type="hidden" name="detail_ProcessId" id="detail_ProcessId" value="${currentProjectContent.projectProcess.projectprocess_Id}">
<input type="hidden" name="projectprocess_Id" id="projectprocess_Id" value="${currentProjectContent.projectProcess.projectprocess_Id}">
<input type="hidden" name="description_Id" id="description_Id" value="${currentProjectContent.projectProcess.projectprocess_Id}">
<input type="hidden" name="project_Id" id="project_Id" value="${currentProjectContent.projectProcess.project_Id}">
<input type="hidden" name="process_Type" id="process_Type" value="${currentProjectContent.projectProcess.process_Type}">
<table id="table_report" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<td style="text-align: center;" colspan="6"><label><b style="color: red"><h2>项目审批</h2></b></label></td>
</tr>
<c:if test="${currentProjectContent.projectProcess.process_Type == '日常请假'}">
<tr>
<th>请假项目名</th>
<td>
<input type="text" id="project_Name" name="project_Name" disabled="disabled"
value="${currentProjectContent.assetAbandonManage.project_Name}" class="col-xs-10 col-sm-5"></td>
<th>请假原因</th>
<td>
<input type="text" id="abandon_reason" name="abandon_reason" disabled="disabled"
value="${currentProjectContent.assetAbandonManage.abandon_reason}" class="col-xs-10 col-sm-5"></td>
<th>审批流程</th>
<td><input type="text" id="abandon_approve" name="abandon_approve" disabled="disabled"
value="${currentProjectContent.assetAbandonManage.abandon_approve}" class="col-xs-10 col-sm-5"></td>
</tr>
</c:if>
<tr>
<th>审批意见</th>
<td colspan="6">
<textarea rows="5" cols="" placeholder="请输入审批意见" style="width:98%;" name="detail_ApproverContent" id="detail_ApproverContent"></textarea>
</td>
</tr>
<tr>
<td style="text-align: center;" colspan="6">
<button type="button" class="btn btn-success" onclick="agreeOption();" style="margin: 20px;">
<i class="ace-icon fa fa-check bigger-110"></i> 审批通过
</button>
<button class="btn btn-primary" type="button"
onClick="disagreeOption();" style="margin: 20px;">
<i class="ace-icon fa fa-check bigger-110"></i> 审批不通过
</button>
<button class="btn btn-danger" type="button"
onClick="cancelOption();" style="margin: 20px;">
<i class="ace-icon fa fa-check bigger-110"></i> 返回
</button>
</td>
</tr>
<tr>
<th>当前状态</th>
<td colspan="6">
<textarea rows="1" cols="80" style="width: 98%;font-size:16px;color: red;" readonly="readonly" >1、请填写对审批项目审批意见2、请进行对本项目的审批操作-同意或者不同意</textarea>
</td>
</tr>
</thead>
</table>
</form>
</div>
<script type="text/javascript">
$(top.hangge());
//点击取消按钮,返回项目流程主界面
function cancelOption() {
alert("自己开发呗")
}
//点击同意按钮的操作
function agreeOption(){
if($('#detail_ApproverContent').val()=="" || $('#detail_ApproverContent').val()==null){
alert("意见不能为空")
$("#detail_ApproverContent").focus();
return false;
}
$('#projectprocessform').attr({action:"/approvalaggree"});
$('#projectprocessform').submit();
}
//点击不同意按钮的操作
function disagreeOption(){
if($('#detail_ApproverContent').val()=="" || $('#detail_ApproverContent').val()==null){
alert("意见不能为空")
$("#detail_ApproverContent").focus();
return false;
}
//规则都符合之后进行判断是否是已经完成的过程跳转到后台(ajax)
var detail_ProcessId =$('#detail_ProcessId').val() ; //获取当前项目过程ID
var process_Type = $('#process_Type').val();//获取当前项目过程的类型
var project_Id = $('#project_Id').val();//获取当前审批项目的ID
$('#projectprocessform').attr({action:"/approvaldisaggree"});
$('#projectprocessform').submit();
}
</script>
</body>
</html>
Controller:
命名:UseApprovalController
备注:因为我这里主要是介绍如何实现工作流,所以,就和上面跳转的Controller代码放一起了,所以各位在实际开发,当然还是最好能为Controller类,这样以后也比较好扩展。
package com.hnu.scw.controller;
import com.hnu.scw.pojo.*;
import com.hnu.scw.service.impl.AssetAbandonImpl;
import com.hnu.scw.service.impl.ProjectApplyImpl;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* @ Author :scw
* @ Date :Created in 下午 3:08 2019/4/28 0028
* @ Description:审批项目使用审批流程的管理
* @ Modified By:
* @Version: $version$
*/
@Controller
public class UseApprovalController {
@Autowired
private AssetAbandonImpl assetAbandon;
@Autowired
private ProjectApplyImpl projectApply;
/**
* 跳转到日常请假需要审批的界面
* @return
*/
@RequestMapping(value = "/showproject")
public ModelAndView showProjectPage(){
ModelAndView mav = new ModelAndView();
//获取审批流程的信息
List<ApprovalProcess> approvalProcess = projectApply.findApproveProcess();
mav.addObject("approvalProcess", approvalProcess);
mav.setViewName("abandontable_add");
return mav;
}
/**
* 处理添加日常请假表(对应数据库中的assetAbandon表)
* @return
* @throws Exception
*/
@RequestMapping(value="/save_abandon")
public String save_abandon(ProjectProcess projectProcess, AssetAbandonManage assetAbandonManage){
//(1)添加请假申请的数据
assetAbandon.saveAssetAbandon(assetAbandonManage);
//(2)添加数据信息到项目审批过程表中
// 获取选取审批流程的ID和名字
String processName = assetAbandonManage.getAbandon_approve();
projectProcess.setProcess_ApprovalName(processName);
// 获取项目申请的id
projectProcess.setProject_Id(assetAbandonManage.getId());
// 需要进行审批项目的项目类型,我这里就用“请假申请”为一个例子,
// 实际中肯定是在前端就已经存在了,不同页面不同
projectProcess.setProcess_Type(assetAbandonManage.getProcess_Type());
// 根据流程ID和顺序,查询对应流程表中的第一个流程节点的ID和名字
Integer processId = projectProcess.getProcess_ApprovalId();
String nodeName = projectApply.findFirstNodeNameByProcessId(processId);
projectProcess.setCurrent_NodeName(nodeName);
projectProcess.setDescription_Passnumber(0);// 通过的人数
projectProcess.setDescription_Refusenumber(0);// 不通过的人数
// 该项目流程的完成状态,开始的状态是未完成
projectProcess.setProcess_FinishStatus( "未完成");
// 刚开始的时候设置的审批节点顺序为第一个,这个不设置也可以,因为数据库中默认了为第一个
projectProcess.setCurrent_NodeOrder(1);
// 设置该项目流程是需要进行审批操作
projectProcess.setProject_Stryle("需要");
// 将数据插入到项目过程表中
projectApply.saveOneProjectProcessInfo(projectProcess);
//----------处理添加审批流程的操作结束----scw--
return "success";
}
/**
* 显示所有需要审批的项目
*/
@RequestMapping(value = "/showprojectlist")
public ModelAndView showProjectList() throws Exception {
ModelAndView mav = new ModelAndView();
List<ProjectProcess> listProject = projectApply.findAllProject();
mav.addObject("listProject",listProject);
mav.setViewName("/project_list");
return mav;
}
/**
* 点击审批按钮进行的详细项目进程的显示
* @return
*/
@RequestMapping(value="/showprojectdetaileprocess")
public ModelAndView editCurrentProjectProcessDetail(Integer projectprocess_Id){
ModelAndView mav = new ModelAndView();
//根据查询到的内容,获取到对应的数据表中的内容
ProcessAndProject currentProjectContent = projectApply.findDifferentContent(projectprocess_Id);
mav.addObject("currentProjectContent", currentProjectContent);
mav.setViewName("/showcurrentproject_edit");
return mav;
}
/**
* 进行审批操作的处理(同意)
*/
@RequestMapping(value = "/approvalaggree")
public String editPorjectPorceeListByYes(ProjectProcess projectProcess, ProjectProcessDetail projectProcessDetail) throws Exception {
//首先当有人审核了,那么就将项目数据库中的审批状态由已提交变为审核中
Integer currentProjecttId = projectProcess.getProject_Id();
//获取审批的类型
String currentProcessType = projectProcess.getProcess_Type();
//修改对应的审批项目的状态为“审核中”,因为当用户提交之后的状态是“已提交”
//而现在有人审核了,那么就对应要修改状态,方便用户看到是否有人审核
projectApply.editProjectManagerStatus(currentProjecttId , currentProcessType);
//(1)将该审核人具体的操作插入到项目流程细节表中
//1:得到该操作的操作时间
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
projectProcessDetail.setDetail_ApprovalTime(df.format(new Date()));
//2:获取当前审批人的userid(实际操作是从session中获取)
//我这里模拟就是直接写死了啊
String userId = "123";
projectProcessDetail.setDetail_ApproverUserID(userId);
//加入审批结果
projectProcessDetail.setDetail_OptionResult("通过");
//3:获取进行操作审批项目的当前处理节点的ID
Integer currentNodeId = projectApply.findCurrentNodeId(projectProcess);
projectProcessDetail.setDetail_CurrentNodeId(currentNodeId);
//4:将数据插入到项目流程细节表中
projectApply.saveProjectProceeDetail(projectProcessDetail);
//(2)查询当前的项目流程中,在项目过程表中,通过的人数,并且+1(因为当前的操作也是通过)
Integer passNumber = projectApply.findProjectDescriptionPassNumber(projectProcess) +1;
//(3)获取当前项目流程,当前审批流程,当前审批节点的所有信息
RelativeInfoProject approvalProcessInfo = projectApply.findRelativeInfo(projectProcess);
//(4)比较当前节点通过人数和当前审批节点需要通过的最小人数的比较
Integer nodeMinNumber = approvalProcessInfo.getApproverNode().getNode_PassNumber();
ProjectProcessDescription projectProcessDescription = new ProjectProcessDescription();
projectProcessDescription.setDescription_ProcessId(projectProcess.getProjectprocess_Id());
if( passNumber < nodeMinNumber){ //处于还是当前流程节点的状态
//当前操作的时间
projectProcessDescription.setDescription_Time(df.format(new Date()));
//当前的项目流程内容
projectProcessDescription.setDescription_Content("当前审批流程-"+approvalProcessInfo.getApprovalProcess().getProcess_Name()+"-审批执行中;审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-不变,通过人数+1");
//在项目流程描述表中更新数据,主要就是更新当前的内容字段
projectApply.saveProjectProcessDescription(projectProcessDescription);
//更新项目过程表对应的过程信息(这个时候其实就是更新通过的人数字段)
projectProcess.setDescription_Passnumber(passNumber);
projectApply.editProjectProcess(projectProcess);
}
else{
//大于或者相等的话,就判断是否又后续节点,有的话就进入下一个节点,
// 没有的话,就为项目流程终止
//当前操作的时间
projectProcessDescription.setDescription_Time(df.format(new Date()));
//判断是否还有后续节点
RelativeInfoProject nextApprovalProcessInfo = projectApply.findIfNextApprovalNode(projectProcess);
//判断得到的后续信息是否为空,如果为空就表示当前节点已经是流程的最后一个节点
if(nextApprovalProcessInfo == null){
//当前的项目流程内容
projectProcessDescription.setDescription_Content("当前审批流程-"+approvalProcessInfo.getApprovalProcess().getProcess_Name()+"-执行完毕;审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-为最后一个节点,该审批过程结束");
//在项目流程描述表中更新数据,主要就是更新当前的内容字段
projectApply.saveProjectProcessDescription(projectProcessDescription);
//更新项目过程表对应的过程信息(这个时候其实就是更新通过的人数字段,过程完成状态)
//当前通过的人数
projectProcess.setDescription_Passnumber(passNumber);
projectApply.editProjectProcessStatus(projectProcess);
//根据项目ID,更新不同表中的流程状态(通过项目审批ID和审批类型)为审批完成并且通过
projectApply.editAprojectManagerStatus(currentProjecttId , currentProcessType , "审批完成(通过)");
}
else{ //还存在后续节点
projectProcessDescription.setDescription_Content("当前审批流程-"+approvalProcessInfo.getApprovalProcess().getProcess_Name()+"-审批执行中;审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-审批完毕,进入后续节点-"+nextApprovalProcessInfo.getApproverNode().getNode_Name()+"-进行审批,通过人数变为0");
//在项目流程描述表中更新数据,主要就是更新当前的内容字段
projectApply.saveProjectProcessDescription(projectProcessDescription);
//更新项目过程表对应的过程信息(这个时候其实就是更新通过的人数字段为0,当前的审批节点名字,审批的第几个次序字段)
//修改当前的节点名称
projectProcess.setCurrent_NodeName(nextApprovalProcessInfo.getApproverNode().getNode_Name());
projectApply.editProjectProcessCurrentNode(projectProcess);
}
}
return "approvalsuccess";
}
/**
* 进行审批操作的处理(不同意)
*/
@RequestMapping(value = "/approvaldisaggree")
public String editPorjectPorceeListByNo(ProjectProcess projectProcess, ProjectProcessDetail projectProcessDetail){
//首先当有人审核了,那么就将项目数据库中的审批状态由已提交变为审核中
Integer currentProjecttId = projectProcess.getProject_Id();
//获取审批的类型
String currentProcessType = projectProcess.getProcess_Type();
projectApply.editProjectManagerStatus(currentProjecttId , currentProcessType);
//(1)将该审核人具体的操作插入到项目流程细节表中
//1:得到该操作的操作时间
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
projectProcessDetail.setDetail_ApprovalTime(df.format((new Date())));
//2:获取当前审批人的userid(实际操作是从session中获取)
//我这里模拟就是直接写死了啊
String userId = "123";
projectProcessDetail.setDetail_ApproverUserID(userId);
//加入审批结果
projectProcessDetail.setDetail_OptionResult("不通过");
//3:获取进行操作审批项目的当前处理节点的ID
Integer nodeId = projectApply.findCurrentNodeId(projectProcess);
projectProcessDetail.setDetail_CurrentNodeId(nodeId);
//4:将数据插入到项目流程细节表中
projectApply.saveProjectProceeDetail(projectProcessDetail);
//(2)查询当前的项目流程中,在项目过程表中,不通过的人数,并且+1(因为当前的操作也是不通过)
Integer refuseNumber = projectApply.findProjectDescriptionRefuseNumber(projectProcess) +1;
//(3)获取当前项目流程,当前审批流程,当前审批节点的所有信息
RelativeInfoProject approvalProcessInfo = projectApply.findRelativeInfo(projectProcess);
//(4)比较当前节点不通过人数和当前审批节点需要通过的最小人数的比较
//获取到当前节点最少需要通过的人数
Integer nodeMinNumber = (Integer) approvalProcessInfo.getApproverNode().getNode_PassNumber();
//获取当前节点中一共的总人数
Integer totalNumber = (Integer) approvalProcessInfo.getApproverNode().getNode_TotalNumber();
//进行比较不通过的人数的情况(二种)
ProjectProcessDescription projectProcessDescription = new ProjectProcessDescription();
projectProcessDescription.setDescription_ProcessId(projectProcess.getProjectprocess_Id());
if(nodeMinNumber <= (totalNumber -refuseNumber )){ //最小通过人数 <= 总人数-拒绝人数,说明还有可能该流程同意,该流程不终止
//添加信息到项目描述表中
projectProcessDescription.setDescription_Content("当前审批流程-"+approvalProcessInfo.getApprovalProcess().getProcess_Name()+"-审批执行中;审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-不变,不通过人数+1");
//当前操作的时间
projectProcessDescription.setDescription_Time(df.format(new Date()));
//在项目流程描述表中更新数据,主要就是更新当前的内容字段
projectApply.saveProjectProcessDescription(projectProcessDescription);
//更新项目过程表对应的过程信息(这个时候其实就是更新不通过的人数字段)
projectProcess.setDescription_Refusenumber(refuseNumber);
projectApply.editProjectProcessRefuseNumber(projectProcess);
}
else{
// 最小通过 > 总人数-拒绝人数,这时候就进行判断当前节点是否可以打回,
// 如果不能,则整个流程结束
//获取当前审批节点是否能够被打回,true为可以打回
String backResult = approvalProcessInfo.getApprovalProcessDetail().getProcessdetail_Back();
//当前操作的时间
projectProcessDescription.setDescription_Time(df.format(new Date()));
//获取项目流程表的序号ID
Integer projectId = projectProcess.getProject_Id();
if("true".equals(backResult)){ //可以打回
//(1)判断当前节点顺序是处于第几级
Integer currentNodeOrder = (Integer) approvalProcessInfo.getProjectProcess().getCurrent_NodeOrder();
if(currentNodeOrder == 1){ //表示的是第一级级别,那么就相当于重新开始
projectProcessDescription.setDescription_Content("当前审批流程-"+approvalProcessInfo.getProjectProcess().getProcess_ApprovalName()+"-由于总人数-不通过人数超过最小通过人数,并且审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-属于第一级能够打回,则重新进行当前审批节点审批处理");
//在项目流程描述表中插入数据,主要就是添加一个内容
projectApply.saveProjectProcessDescription(projectProcessDescription);
//根据项目进程ID,更新项目过程表中的通过和不通过的人数信息全部为0,还有审批状态为未完成
projectApply.editCurrentProjectProcessContent(projectProcess);
//根据项目进程ID,删除所有在项目明细表中的数据
projectApply.editDeletProjectProcessDeatil(projectId);
//因为又处于第一级审核并且处理审批的人数重新都设置为0了,那么这时候需要将对应项目中的审批状态设置为已提交,这样的话,就可以方便各个项目进行修改
projectApply.editAgainDifferenProjectStatus(currentProjecttId , currentProcessType);
}
else{ //表示要返回上一级节点重新进行处理
projectProcessDescription.setDescription_Content("当前审批流程-"+approvalProcessInfo.getProjectProcess().getProcess_ApprovalName()+"-由于总人数-不通过人数超过最小通过人数,并且审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-属于第"+currentNodeOrder+"级能够打回,则重新进行当前审批节点的前一级审批节点处理");
//在项目流程描述表中插入数据,主要就是添加一个数据
projectApply.saveProjectProcessDescription(projectProcessDescription);
//根据当前审批节点的ID,审批人员的userid,删除当前审批节点中审批人员的操作信息
//获取当前审批ID
Integer currentNodeId = (Integer) approvalProcessInfo.getApproverNode().getNode_Id();
//查询当前节点对应的UserId信息
List<String> approverUserIds = projectApply.findAllUserIdByNodeId(currentNodeId);
//删除当前审批节点中对应审批用户的操作信息
ProjectProcessDetail newProjectDetail = new ProjectProcessDetail();
//对应的项目流程ID
newProjectDetail.setDetail_ProcessId(projectId);
for(int i =0 ; i< approverUserIds.size() ; i++){
//审核人员ID
newProjectDetail.setDetail_ApproverUserID(approverUserIds.get(i));
projectApply.editProjectProcessDetailByUserID(newProjectDetail);
}
//获取上一级的审批顺序
Integer lastNodeOrder = currentNodeOrder - 1;
//根据项目流程ID,更新项目流程的审批顺序的字段和通过人数和不通过人数信息,审批是否完成
projectApply.editProjectProcessLastOrderInfo(projectId);
//获取上一级审批的相关的内容信息
RelativeInfoProject lastPageDate = projectApply.findRelativeInfo(projectProcess);
//根据项目流程ID,更新当前项目过程ID中的审批节点的名字
ProjectProcess newProjectProcess = new ProjectProcess();
// 获取当前的节点名字
newProjectProcess.setCurrent_NodeName(lastPageDate.getApproverNode().getNode_Name());
//项目过程ID
newProjectProcess.setProject_Id(projectId);
projectApply.editProjectProcessNodeName(newProjectProcess);
//将当前修改了的审批节点中的审批人员的数据从项目明细表中进行删除,因为这个节点的人员之前已经有操作信息
//获取当前审批ID
currentNodeId = lastPageDate.getApproverNode().getNode_Id();
//查询当前节点对应的UserId信息
approverUserIds = projectApply.findAllUserIdByNodeId(currentNodeId);
//删除当前审批节点中对应审批用户的操作信息
//对应的项目流程ID
projectProcessDetail.setDetail_ProcessId(projectId);
for(int i =0 ; i< approverUserIds.size() ; i++){
//审核人员ID
projectProcessDetail.setDetail_ApproverUserID(approverUserIds.get(i));
projectApply.editProjectProcessDetailByUserID(projectProcessDetail);
}
//最终完成处理
//如果返回的上一级是第一级,那么还需要进行下面的一个处理
if(currentNodeOrder == 2){
//因为又处于第一级审核并且处理审批的人数重新都设置为0了,那么这时候需要将对应项目中的审批状态设置为已提交,这样的话,就可以方便各个项目进行修改
projectApply.editAgainDifferenProjectStatus(currentProjecttId , currentProcessType);
}
}
}
else{ //不能够被打回,则将该项目流程直接修改完成状态
projectProcessDescription.setDescription_Content( "当前审批流程-"+approvalProcessInfo.getProjectProcess().getProcess_ApprovalName()+"-由于总人数-不通过人数超过最小通过人数,并且审批节点-"+approvalProcessInfo.getApproverNode().getNode_Name()+"-无法被打回,则审批过程结束");
//在项目流程描述表中插入数据,主要就是添加内容
projectApply.saveProjectProcessDescription(projectProcessDescription);
//更新项目过程表对应的过程信息(这个时候其实就是更新不通过的人数字段,过程是否完成状态)
//当前不通过的人数
projectProcess.setDescription_Refusenumber(refuseNumber);
projectApply.editProjectProcessStatusFinished(projectProcess);
//根据项目ID,更新不同表中的流程状态(通过项目审批ID和审批类型)
projectApply.editAprojectManagerStatus(currentProjecttId , currentProcessType , "审批完成(不通过)");
}
}
return "approvalsuccess";
}
}
Service:
package com.hnu.scw.service.impl;
import com.hnu.scw.mapper.ApprovalProjectMapper;
import com.hnu.scw.pojo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 审批处理相关的代码
* @author scw
*
*/
@Service
public class ProjectApplyImpl {
@Autowired
private ApprovalProjectMapper approvalProjectMapper;
/**
* 查询审批流程 增加项目的时候进行选择
* @return
*/
public List<ApprovalProcess> findApproveProcess() {
return approvalProjectMapper.findList();
}
/**
* 根据审批流程Id获取第一处理的节点名
* @param proceesId
* @return
*/
public String findFirstNodeNameByProcessId(Integer proceesId){
return approvalProjectMapper.findFirstNodeName(proceesId);
}
/**
* 添加一条需要审批的数据到审批项目表中
* @param projectProcess
*/
public void saveOneProjectProcessInfo(ProjectProcess projectProcess){
approvalProjectMapper.saveOneProjectProcessInfo(projectProcess);
}
/**
* 返回所有审批的项目
* @return
*/
public List<ProjectProcess> findAllProject(){
return approvalProjectMapper.findAllProject();
}
/**
* 根据项目审批Id获取对应的详细信息
* @param projectProcessId
* @return
*/
public ProjectProcess findCurrentProjectDetail(Integer projectProcessId){
return approvalProjectMapper.findCurrentProjectDetail(projectProcessId);
}
/**
* 查询对应审批项目和对应项目审批流程的相关详细信息
* @param projectProcessId
* @return
*/
public ProcessAndProject findDifferentContent(Integer projectProcessId){
return approvalProjectMapper.findDifferentContent(projectProcessId);
}
/**
* 修改对应项目的审批状态
* @param processId
* @param projectType
*/
public void editProjectManagerStatus(Integer processId, String projectType){
if("日常请假".equals(projectType)){
approvalProjectMapper.editProjectManagerStatus(processId);
}
}
/**
* 根据当前审批项目的ID和类型,获得对应操作的审批节点的信息ID
* @param projectProcess
* @return
*/
public Integer findCurrentNodeId(ProjectProcess projectProcess){
return approvalProjectMapper.findCurrentNodeId(projectProcess);
}
/**
* 将审批细节的信息插入到数据表中(aproject_processdetail)
* @param projectProcessDetail
*/
public void saveProjectProceeDetail(ProjectProcessDetail projectProcessDetail){
approvalProjectMapper.saveProjectProceeDetail(projectProcessDetail);
}
/**
* 将对应项目审批信息中的通过人数+1,并返回人数
* @param projectProcess
* @return
*/
public Integer findProjectDescriptionPassNumber(ProjectProcess projectProcess){
return approvalProjectMapper.findProjectDescriptionPassNumber(projectProcess);
}
/**
* 将对应项目审批信息中的不通过人数+1,并返回人数
* @param projectProcess
* @return
*/
public Integer findProjectDescriptionRefuseNumber(ProjectProcess projectProcess){
return approvalProjectMapper.findProjectDescriptionRefuseNumber(projectProcess);
}
/**
* 获取项目审批相关联表的详细信息
* @param projectProcess
* @return
*/
public RelativeInfoProject findRelativeInfo(ProjectProcess projectProcess){
return approvalProjectMapper.findRelativeInfo(projectProcess);
}
/**
* 插入数据到项目审批流程表
* @param projectProcessDescription
*/
public void saveProjectProcessDescription(ProjectProcessDescription projectProcessDescription){
approvalProjectMapper.saveProjectProcessDescription(projectProcessDescription);
}
/**
* 更新当前审批项目中不通过的人数字段信息
* @param projectProcess
*/
public void editProjectProcessRefuseNumber(ProjectProcess projectProcess){
approvalProjectMapper.editProjectProcessRefuseNumber(projectProcess);
}
/**
* 根据项目审批表中的通过人数的字段信息
* @param projectProcess
*/
public void editProjectProcess(ProjectProcess projectProcess){
approvalProjectMapper.editProjectProcess(projectProcess);
}
/**
* 判断当前审批完成的节点后是否还有后续需要审批的节点
* @param projectProcess
* @return
*/
public RelativeInfoProject findIfNextApprovalNode(ProjectProcess projectProcess){
return approvalProjectMapper.findIfNextApprovalNode(projectProcess);
}
/**
* 更新审批项目中的通过人数和审批状态字段信息
* @param projectProcess
*/
public void editProjectProcessStatus(ProjectProcess projectProcess){
approvalProjectMapper.editProjectProcessStatus(projectProcess);
}
/**
* 根据项目ID,修改项目审批的结果
* @param projectId:各自项目的ID ,
* currentProcessType:项目的类型 ,
* approResult:审批的结果---审批通过并且是否通过
*/
public void editAprojectManagerStatus(Integer projectId ,String currentProcessType ,String approResult){
if("日常请假".equals(currentProcessType)){
AssetAbandonManage assetAbandonManage = new AssetAbandonManage();
assetAbandonManage.setId(projectId);
assetAbandonManage.setApprove_status(approResult);
approvalProjectMapper.editAprojectManagerStatus(assetAbandonManage);
}
}
/**
* 更新当前的审批项目的下一个节点的内容
* @param projectProcess
*/
public void editProjectProcessCurrentNode(ProjectProcess projectProcess){
approvalProjectMapper.editProjectProcessCurrentNode(projectProcess);
}
/**
* 将对应的审批项目的信息更新(因此此时相当于重新开始)
* @param projectProcess
*/
public void editCurrentProjectProcessContent(ProjectProcess projectProcess){
approvalProjectMapper.editCurrentProjectProcessContent(projectProcess);
}
/**
* 根据项目进程ID,删除所有的项目明细表中的数据
* @param projectId
*/
public void editDeletProjectProcessDeatil(Integer projectId){
approvalProjectMapper.editDeletProjectProcessDeatil(projectId);
}
/**
* 当重新返回到第一级流程处理的时候,需要将各个项目中的状态设置为“已提交”,这样能够方便各个项目对内容进行修改
* @param currentProjecttId:各个需要审批的项目ID
* @param currentProcessType:需要审批的项目的类型,是项目立项还是耗材申请,还是报废申请等
*/
public void editAgainDifferenProjectStatus(Integer currentProjecttId, String currentProcessType){
//判断属于的是什么审批项目,这样处理的表也就会不一样
//判断一下需要进行显示的数据是属于哪个表里面(因为审批项目中可能是在资产,报废和维修表中)
if ("日常请假".equals(currentProcessType)) {
approvalProjectMapper.editAgainDifferenProjectStatus(currentProjecttId);
}
}
/**
* 根据节点ID,返回所有的审核人员的userid
* @param nodeId
* @return
*/
public List<String> findAllUserIdByNodeId(Integer nodeId){
return approvalProjectMapper.findAllUserIdByNodeId(nodeId);
}
/**
* 根据审批人员ID,删除对应的项目明细表中之前的操作信息
* @param newProjectDetail
*/
public void editProjectProcessDetailByUserID(ProjectProcessDetail newProjectDetail) {
approvalProjectMapper.editProjectProcessDetailByUserID(newProjectDetail);
}
/**
* 根据项目流程ID,更新项目流程的审批顺序的字段和通过人数和不通过人数信息
* @param projectId
*/
public void editProjectProcessLastOrderInfo(Integer projectId) {
approvalProjectMapper.editProjectProcessLastOrderInfo(projectId);
}
/**
* 根据项目流程ID,更新当前节点的名字
* @param projectProcess
*/
public void editProjectProcessNodeName(ProjectProcess projectProcess) {
approvalProjectMapper.editProjectProcessNodeName(projectProcess);
}
/**
* 根据项目流程ID,更新不通过人数和是否完成状态
* @param projectProcess
*/
public void editProjectProcessStatusFinished(ProjectProcess projectProcess){
approvalProjectMapper.editProjectProcessStatusFinished(projectProcess);
}
}
Mapper:
package com.hnu.scw.mapper;
import com.hnu.scw.pojo.*;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* @ Author :scw
* @ Date :Created in 下午 3:21 2018/6/15 0015
* @ Description:对应于审批项目的mapper操作接口
* @ Modified By:
* @Version: $version$
*/
public interface ApprovalProjectMapper {
/**
* 查询系统的所有审批流程内容
* @return
*/
List<ApprovalProcess> findList();
/**
* 根据流程ID获取第一个审批节点
* @param proceesId
* @return
*/
String findFirstNodeName(Integer proceesId);
/**
* 插入一条项目审批数据到项目审批数据库中
* @param projectProcess
*/
void saveOneProjectProcessInfo(ProjectProcess projectProcess);
/**
* 返回所有需要审批的项目
* @return
*/
List<ProjectProcess> findAllProject();
ProjectProcess findCurrentProjectDetail(Integer projectProcessId);
ProcessAndProject findDifferentContent(@Param(value = "projectprocess_Id") Integer projectProcessId);
void editProjectManagerStatus(Integer processId);
Integer findCurrentNodeId(ProjectProcess projectProcess);
void saveProjectProceeDetail(ProjectProcessDetail projectProcessDetail);
Integer findProjectDescriptionPassNumber(ProjectProcess projectProcess);
Integer findProjectDescriptionRefuseNumber(ProjectProcess projectProcess);
RelativeInfoProject findRelativeInfo(ProjectProcess projectProcess);
void saveProjectProcessDescription(ProjectProcessDescription projectProcessDescription);
void editProjectProcess(ProjectProcess projectProcess);
RelativeInfoProject findIfNextApprovalNode(ProjectProcess projectProcess);
void editProjectProcessStatus(ProjectProcess projectProcess);
void editAprojectManagerStatus(AssetAbandonManage assetAbandonManage);
void editProjectProcessCurrentNode(ProjectProcess projectProcess);
void editProjectProcessRefuseNumber(ProjectProcess projectProcess);
void editCurrentProjectProcessContent(ProjectProcess projectProcess);
void editDeletProjectProcessDeatil(Integer projectId);
void editAgainDifferenProjectStatus(Integer currentProjecttId);
List<String> findAllUserIdByNodeId(Integer nodeId);
void editProjectProcessDetailByUserID(ProjectProcessDetail newProjectDetail);
void editProjectProcessLastOrderInfo(Integer projectId);
void editProjectProcessNodeName(ProjectProcess projectProcess);
void editProjectProcessStatusFinished(ProjectProcess projectProcess);
}
MapperXml:
<?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">
<!-- 写Sql语句 -->
<mapper namespace="com.hnu.scw.mapper.ApprovalProjectMapper">
<resultMap id="approvalproject" type="com.hnu.scw.pojo.ApprovalProcess">
<id property="process_Id" column="process_Id"/>
<result property="process_Name" column="process_Name"/>
<result property="process_Content" column="process_Content"/>
<result property="process_Type" column="process_Type"/>
</resultMap>
<resultMap id="projectprocess" type="com.hnu.scw.pojo.ProjectProcess">
<id property="projectprocess_Id" column="projectprocess_Id"/>
<result property="project_Id" column="project_Id"/>
<result property="project_Name" column="project_Name"/>
<result property="project_Stryle" column="project_Stryle"/>
<result property="current_NodeOrder" column="current_NodeOrder"/>
<result property="process_FinishStatus" column="process_FinishStatus"/>
<result property="process_ApprovalId" column="process_ApprovalId"/>
<result property="process_ApprovalName" column="process_ApprovalName"/>
<result property="current_NodeName" column="current_NodeName"/>
<result property="description_Passnumber" column="description_Passnumber"/>
<result property="description_Refusenumber" column="description_Refusenumber"/>
<result property="process_Type" column="process_Type"/>
</resultMap>
<resultMap id="processAndProject" type="com.hnu.scw.pojo.ProcessAndProject">
<association property="assetAbandonManage" javaType="com.hnu.scw.pojo.AssetAbandonManage">
<id property="id" column="id"/>
<result property="process_Type" column="process_Type"/>
<result property="project_Name" column="project_Name"/>
<result property="abandon_reason" column="abandon_reason"/>
<result property="abandon_approve" column="abandon_approve"/>
<result property="approve_status" column="approve_status"/>
</association>
<association property="projectProcess" javaType="com.hnu.scw.pojo.ProjectProcess">
<id property="projectprocess_Id" column="projectprocess_Id"/>
<result property="project_Id" column="project_Id"/>
<result property="project_Name" column="project_Name"/>
<result property="project_Stryle" column="project_Stryle"/>
<result property="current_NodeOrder" column="current_NodeOrder"/>
<result property="process_FinishStatus" column="process_FinishStatus"/>
<result property="process_ApprovalId" column="process_ApprovalId"/>
<result property="process_ApprovalName" column="process_ApprovalName"/>
<result property="current_NodeName" column="current_NodeName"/>
<result property="description_Passnumber" column="description_Passnumber"/>
<result property="description_Refusenumber" column="description_Refusenumber"/>
<result property="process_Type" column="process_Type"/>
</association>
</resultMap>
<resultMap id="relativeInfoProject" type="com.hnu.scw.pojo.RelativeInfoProject">
<association property="projectProcess" javaType="com.hnu.scw.pojo.ProjectProcess">
<id property="projectprocess_Id" column="projectprocess_Id"/>
<result property="project_Id" column="project_Id"/>
<result property="project_Name" column="project_Name"/>
<result property="project_Stryle" column="project_Stryle"/>
<result property="current_NodeOrder" column="current_NodeOrder"/>
<result property="process_FinishStatus" column="process_FinishStatus"/>
<result property="process_ApprovalId" column="process_ApprovalId"/>
<result property="process_ApprovalName" column="process_ApprovalName"/>
<result property="current_NodeName" column="current_NodeName"/>
<result property="description_Passnumber" column="description_Passnumber"/>
<result property="description_Refusenumber" column="description_Refusenumber"/>
<result property="process_Type" column="process_Type"/>
</association>
<association property="approvalProcess" javaType="com.hnu.scw.pojo.ApprovalProcess">
<id property="process_Id" column="process_Id"/>
<result property="process_Name" column="process_Name"/>
<result property="process_Content" column="process_Content"/>
<result property="process_Type" column="process_Type"/>
</association>
<association property="approverNode" javaType="com.hnu.scw.pojo.ApproverNode">
<id property="node_Id" column="node_Id"/>
<result property="node_Name" column="node_Name"/>
<result property="node_PassNumber" column="node_PassNumber"/>
<result property="node_TotalNumber" column="node_TotalNumber"/>
<result property="node_Description" column="node_Description"/>
</association>
<association property="approvalProcessDetail" javaType="com.hnu.scw.pojo.ApprovalProcessDetail">
<id property="process_Id" column="process_Id"/>
<result property="processdetail_Id" column="processdetail_Id"/>
<result property="processdetail_NodeId" column="processdetail_NodeId"/>
<result property="processdetail_Nodeorder" column="processdetail_Nodeorder"/>
<result property="processdetail_Back" column="processdetail_Back"/>
</association>
</resultMap>
<!--获取系统所有的审批流程信息-->
<select id="findList" resultMap="approvalproject">
select
*
from
sys_process_approval
</select>
<!-- 根据选择的审批流程获取对应的第一个审批节点的名字,主要用来显示的 -->
<select id="findFirstNodeName" parameterType="Integer" resultType="String">
select
sys_approvnode.node_Name
from
sys_approvnode ,sys_process_detail
where
sys_process_detail.processdetail_Id = #{processdetail_Id}
and
sys_process_detail.processdetail_NodeId = sys_approvnode.node_Id
and
sys_process_detail.processdetail_Nodeorder = 1
</select>
<insert id="saveOneProjectProcessInfo" parameterType="com.hnu.scw.pojo.ProjectProcess">
insert into
aproject_process(
project_Name,
project_Id,
project_Stryle,
current_NodeOrder,
process_FinishStatus,
process_ApprovalId,
process_ApprovalName,
current_NodeName,
description_Passnumber,
description_Refusenumber,
process_Type
)values(
#{project_Name},
#{project_Id},
#{project_Stryle},
#{current_NodeOrder},
#{process_FinishStatus},
#{process_ApprovalId},
#{process_ApprovalName},
#{current_NodeName},
#{description_Passnumber},
#{description_Refusenumber},
#{process_Type}
)
</insert>
<!--获取系统所有的需要审批的项目-->
<select id="findAllProject" resultMap="projectprocess">
select
*
from
aproject_process
</select>
<!--根据项目审批ID获取对应的项目审批详细细节-->
<select id="findCurrentProjectDetail" parameterType="java.lang.Integer" resultMap="projectprocess">
select
*
from
aproject_process
WHERE
projectprocess_Id = #{processId}
</select>
<!-- 根据项目ID和审批类型,查询对应的项目内容(模拟处理请假申请) -->
<select id="findDifferentContent" parameterType="java.lang.Integer" resultMap="processAndProject">
select *
from
asset_abandon
,
aproject_process
where
aproject_process.projectprocess_Id = ${projectprocess_Id}
and
asset_abandon.id = aproject_process.project_Id
</select>
<!-- 根据项目ID,更新日常请假申请表对应id的审核状态,为审核中 -->
<update id="editProjectManagerStatus" parameterType="Integer">
update
asset_abandon
set
approve_status = "审批中"
where
id = #{id}
</update>
<!-- 根据审批项目的ID和类型,获取到当前处理的审批节点的ID -->
<select id="findCurrentNodeId" parameterType="com.hnu.scw.pojo.ProjectProcess" resultType="Integer">
select
sys_process_detail.processdetail_NodeId
from
aproject_process ,sys_process_detail
where
aproject_process.project_Id =#{project_Id}
and
aproject_process.process_Type =#{process_Type}
and
aproject_process.process_ApprovalId = sys_process_detail.processdetail_Id
and
aproject_process.current_NodeOrder = sys_process_detail.processdetail_Nodeorder
</select>
<!-- 插入数据到项目流程细节表中aproject_processdetail -->
<insert id="saveProjectProceeDetail" parameterType="com.hnu.scw.pojo.ProjectProcessDetail">
insert into
aproject_processdetail(
detail_ProcessId,
detail_ApproverContent,
detail_ApproverUserID,
detail_ApprovalTime,
detail_OptionResult,
detail_CurrentNodeId
)values(
#{detail_ProcessId},
#{detail_ApproverContent},
#{detail_ApproverUserID},
#{detail_ApprovalTime},
#{detail_OptionResult},
#{detail_CurrentNodeId}
)
</insert>
<!-- 根据项目流程表中的ID,获取对该流程中当前节点通过的人数 -->
<select id="findProjectDescriptionPassNumber" parameterType="com.hnu.scw.pojo.ProjectProcess" resultType="Integer">
select
description_Passnumber
from
aproject_process
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</select>
<!-- 根据内容,查询多个表的内容 -->
<select id="findRelativeInfo" parameterType="com.hnu.scw.pojo.ProjectProcess" resultMap="relativeInfoProject">
select *
from
aproject_process , sys_approvnode , sys_process_approval,sys_process_detail
where
aproject_process.projectprocess_Id = #{projectprocess_Id}
and
aproject_process.process_Type = #{process_Type}
and
aproject_process.process_ApprovalId = sys_process_approval.process_Id
and
sys_process_detail.processdetail_Id = aproject_process.process_ApprovalId
and
aproject_process.current_NodeOrder = sys_process_detail.processdetail_Nodeorder
and
sys_process_detail.processdetail_NodeId = sys_approvnode.node_Id
</select>
<!-- 插入数据到项目过程描述表中 -->
<insert id="saveProjectProcessDescription" parameterType="com.hnu.scw.pojo.ProjectProcessDescription">
insert into
aproject_prcessdescription(
description_ProcessId,
description_Time,
description_Content
)values(
#{description_ProcessId},
#{description_Time},
#{description_Content}
)
</insert>
<!-- 更新对应的项目过程表中的通过人数字段 -->
<update id="editProjectProcess" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
description_Passnumber = #{description_Passnumber}
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</update>
<!-- 根据当前审批流程的节点顺序,判断是否还有后续节点 -->
<select id="findIfNextApprovalNode" parameterType="com.hnu.scw.pojo.ProjectProcess" resultMap="relativeInfoProject">
select *
from
aproject_process , sys_approvnode , sys_process_approval,sys_process_detail
where
aproject_process.projectprocess_Id = #{projectprocess_Id}
and
aproject_process.process_Type = #{process_Type}
and
aproject_process.process_ApprovalId = sys_process_approval.process_Id
and
sys_process_detail.processdetail_Id = aproject_process.process_ApprovalId
and
(aproject_process.current_NodeOrder+1) = sys_process_detail.processdetail_Nodeorder
and
sys_process_detail.processdetail_NodeId = sys_approvnode.node_Id
</select>
<!-- 更新对应的项目过程表中的通过人数字段和修改是否完成字段 -->
<update id="editProjectProcessStatus" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
description_Passnumber = #{description_Passnumber},
process_FinishStatus ="流程结束,审批工作通过"
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</update>
<!-- 根据项目ID,更新报废申请表的审核状态 ,为审核完成-->
<update id="editAprojectManagerStatus" parameterType="com.hnu.scw.pojo.AssetAbandonManage">
update
asset_abandon
set
approve_status = #{approve_status}
where
id = #{id}
</update>
<!-- 更新对应的项目过程表中的通过人数字段和当前的审批节点名称和审批的当前次序 -->
<update id="editProjectProcessCurrentNode" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
description_Passnumber = 0,
description_Refusenumber = 0,
current_NodeName = #{current_NodeName},
current_NodeOrder =#{current_NodeOrder}+1
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</update>
<!-- 根据项目流程表中的ID,获取对该流程中当前节点不通过的人数 -->
<select id="findProjectDescriptionRefuseNumber" parameterType="com.hnu.scw.pojo.ProjectProcess" resultType="Integer">
select
description_Refusenumber
from
aproject_process
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</select>
<!-- 更新对应的项目过程表中的不通过人数字段 -->
<update id="editProjectProcessRefuseNumber" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
description_Refusenumber = #{description_Refusenumber}
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</update>
<!-- 根据项目流程ID,更新对应的通过和不通过和流程状态数据-->
<update id="editCurrentProjectProcessContent" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
description_Passnumber=0,
description_Refusenumber=0,
process_FinishStatus = "未完成"
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</update>
<!-- 根据项目过程ID,删除项目明细表中的数据(当前审批节点为第一级的时候)-->
<delete id="editDeletProjectProcessDeatil" parameterType="Integer">
delete
from
aproject_processdetail
where
detail_ProcessId = #{detail_ProcessId}
</delete>
<!-- 这个是修改日常请假信息 -->
<update id="editAgainDifferenProjectStatus" parameterType="Integer">
update
asset_abandon
set
approve_status = "已提交"
where
id = #{id}
</update>
<!-- 根据节点ID,返回所有对应节点中审批人员的userid的String数组 -->
<select id="findAllUserIdByNodeId" parameterType="Integer" resultType="String">
select approvnode_UserId
from
sys_approvnodepeople
where
approvnode_nodeId = #{approvnode_nodeId}
</select>
<!--根据审批人员ID,删除过程明细表中之前的数据信息-->
<delete id="editProjectProcessDetailByUserID" parameterType="com.hnu.scw.pojo.ProjectProcessDetail">
delete
from
aproject_processdetail
where
detail_ProcessId = #{detail_ProcessId}
and
detail_ApproverUserID = #{detail_ApproverUserID}
</delete>
<!--根据项目ID,更新当前的处理审批的节点顺序和节点名字 -->
<update id="editProjectProcessLastOrderInfo" parameterType="Integer">
update
aproject_process
set
description_Refusenumber = 0,
description_Passnumber = 0,
current_NodeOrder = current_NodeOrder -1,
process_FinishStatus = "未完成"
where
projectprocess_Id = #{projectprocess_Id}
</update>
<!-- 根据项目ID,更新当前的处理审批的节点名字 -->
<update id="editProjectProcessNodeName" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
current_NodeName = #{current_NodeName}
where
projectprocess_Id = #{projectprocess_Id}
</update>
<update id="editProjectProcessStatusFinished" parameterType="com.hnu.scw.pojo.ProjectProcess">
update
aproject_process
set
description_Passnumber = #{description_Passnumber},
process_FinishStatus ="流程结束,审批工作不通过(不通过人数大于通过人数)"
where
projectprocess_Id = #{projectprocess_Id}
and
process_Type = #{process_Type}
</update>
</mapper>
备注:这个部分的代码可能会比较长,有些地方是能够优化,写得更紧简洁的,所以,希望你们能够在基于这个的前提,自己发挥代码能力去优化一下,我这里就是抛砖引玉。
恳请大家认真分析一下里面的逻辑,讲真!!!还是挺复杂的,但是我写得这个是比较通用的,因为节点、流程反转都可以实现,功能是比较全
总结
(1)本篇完成工作流的整体流程功能的代码编写实现。
(2)对工作流的处理有了更为深层次的理解。
(3)整体的功能相对是比较强大(因为可以控制反转、多级审批等等)。
(4)以后如果需要使用,可以直接进行打包使用,相对比较简单。
(5)因为项目里面用了Maven管理,所以有需要的大家可以自己抽取打包成jar,或者以后将整个工程作为一个module进行其他项目的整合使用。
(6)代码里面并不是所有功能都加了,比如权限控制和数据控制(不同用户显示不同条目),这些都是相对简单的,所以不作为本文的重点。
(7)代码存在冗余,大家可以根据需求进行优化,仅供参考。
(8)欢迎大家互相交流。
(9)oh No,花了一些时间重写这些还是挺花时间的,介意不介意给个关注呢?哈哈
源代码
(1)Github:
- git@github.com:qq496616246/CustomActiviti.git
- https://github.com/qq496616246/CustomActiviti.git
(2)百度云:
链接:https://pan.baidu.com/s/1-U4ENfjAHhaZxiI0L21OkA
提取码:swvv
(3)如果失效了就留言给我就可以了哈~