Java项目(一)--MyBatis实现OA系统项目实战(7)--开发多级审批流程
开发多级审批流程
请假流程
设计约束
每一个请假单对应一个审批流程。
请假单创建后,按业务规则生成部门经理、总经理审批任务。
审批任务的经办人只能审批自己辖区内的请假申请。
所有审批任务“通过”,代表请假已经批准。
任意审批任务“驳回”操作,其余审批任务取消,请假申请驳回。
请假流程中的任意节点产生的操作都要生成对应的系统通知。
工作流程表设计
打开navicat,创建adm_leave_form请假单表
创建adm_process_flow审批任务流程表
创建sys_notice消息通知表
实现Dao与数据交互
先将实体类创建好
package com.ql.oa.entity;import java.util.Date;public class LeaveForm {private Long formId;private Long employeeId;private Integer formType;private Date startTime;private Date endTime;private String reason;private Date createTime;private String state;public Long getFormId() {return formId;}public void setFormId(Long formId) {this.formId = formId;}public Long getEmployeeId() {return employeeId;}public void setEmployeeId(Long employeeId) {this.employeeId = employeeId;}public Integer getFormType() {return formType;}public void setFormType(Integer formType) {this.formType = formType;}public Date getStartTime() {return startTime;}public void setStartTime(Date startTime) {this.startTime = startTime;}public Date getEndTime() {return endTime;}public void setEndTime(Date endTime) {this.endTime = endTime;}public String getReason() {return reason;}public void setReason(String reason) {this.reason = reason;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public String getState() {return state;}public void setState(String state) {this.state = state;}
}
package com.ql.oa.entity;import java.util.Date;public class ProcessFlow {private Long processId;private Long formId;private Long operatorId;private String action;private String result;private String reason;private Date createTime;private Date auditTime;private Integer orderNo;private String state;private Integer isLast;public Long getProcessId() {return processId;}public void setProcessId(Long processId) {this.processId = processId;}public Long getFormId() {return formId;}public void setFormId(Long formId) {this.formId = formId;}public Long getOperatorId() {return operatorId;}public void setOperatorId(Long operatorId) {this.operatorId = operatorId;}public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getResult() {return result;}public void setResult(String result) {this.result = result;}public String getReason() {return reason;}public void setReason(String reason) {this.reason = reason;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getAuditTime() {return auditTime;}public void setAuditTime(Date auditTime) {this.auditTime = auditTime;}public Integer getOrderNo() {return orderNo;}public void setOrderNo(Integer orderNo) {this.orderNo = orderNo;}public String getState() {return state;}public void setState(String state) {this.state = state;}public Integer getIsLast() {return isLast;}public void setIsLast(Integer isLast) {this.isLast = isLast;}
}
package com.ql.oa.entity;import java.util.Date;public class Notice {private Long noticeId;private Long receiverId;private String content;private Date createTime;public Notice(){}public Notice(Long receiverId , String content){this.receiverId = receiverId;this.content = content;this.createTime = new Date();}public Long getNoticeId() {return noticeId;}public void setNoticeId(Long noticeId) {this.noticeId = noticeId;}public Long getReceiverId() {return receiverId;}public void setReceiverId(Long receiverId) {this.receiverId = receiverId;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}
}
然后把每个实体类的数据交互的接口Dao创建好并填写新增数据的方法:
package com.ql.oa.dao;import com.ql.oa.entity.LeaveForm;public interface LeaveFormDao {public void insert(LeaveForm form);
}
package com.ql.oa.dao;import com.ql.oa.entity.ProcessFlow;public interface ProcessFlowDao {public void insert(ProcessFlow processFlow);
}
package com.ql.oa.dao;import com.ql.oa.entity.Notice;public interface NoticeDao {public void insert(Notice notice);
}
然后在resources\mappers下创建mapper文件并在mybatis-config.xml里配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ql.oa.dao.LeaveFormDao"><insert id="insert" parameterType="com.ql.oa.entity.LeaveForm"useGeneratedKeys="true" keyProperty="formId" keyColumn="form_id">INSERT INTO adm_leave_form( employee_id, form_type, start_time, end_time, reason, create_time, state)VALUES ( #{employeeId}, #{formType}, #{startTime}, #{endTime}, #{reason}, #{createTime}, #{state})</insert>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ql.oa.dao.ProcessFlowDao"><insert id="insert" parameterType="com.ql.oa.entity.ProcessFlow"useGeneratedKeys="true" keyColumn="process_id" keyProperty="processId">INSERT INTO adm_process_flow(form_id, operator_id, action, result, reason, create_time , audit_time , order_no , state,is_last)VALUES (#{formId}, #{operatorId}, #{action}, #{result}, #{reason}, #{createTime} , #{auditTime} , #{orderNo} , #{state} , #{isLast});</insert>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ql.oa.dao.NoticeDao"><insert id="insert" parameterType="com.ql.oa.entity.Notice"useGeneratedKeys="true" keyProperty="noticeId" keyColumn="notice_id">INSERT INTO sys_notice( receiver_id, content, create_time) VALUES (#{receiverId}, #{content}, #{createTime})</insert>
</mapper>
<mappers><mapper resource="mappers/user.xml"/><mapper resource="mappers/rbac.xml"/><mapper resource="mappers/employee.xml"/><mapper resource="mappers/department.xml"/><mapper resource="mappers/leave_form.xml"/><mapper resource="mappers/process_flow.xml"/><mapper resource="mappers/notice.xml"/></mappers>
开发请假申请功能
在EmployeeDao接口中新增一个方法,并且在相应的employee.xml中添加实现:
/*** 根据传入员工对象获取上级主管对象* @param employee 员工对象* @return 上级主管对象*/public Employee selectLeader(@Param("emp") Employee employee);
<select id="selectLeader" parameterType="com.ql.oa.entity.Employee" resultType="com.ql.oa.entity.Employee">select * from adm_employeewhere<if test="emp.level < 7">level = 7 and department_id = #{emp.departmentId}</if><if test="emp.level == 7">level = 8</if><if test="emp.level == 8">employee_id = #{emp.employeeId}</if></select>
在com.ql.oa.service包下创建LeaveFormService.java请假单流程业务类,并编写创建请假单的方法
/*** 请假单流程服务*/
public class LeaveFormService {/*** 创建请假单* @param form 前端输入的请假单数据* @return 持久化后的请假单对象*/public LeaveForm createLeaveForm(LeaveForm form){LeaveForm savedForm = (LeaveForm)MyBatisUtils.executeUpdate(sqlSession -> {//1.持久化form表单数据,8级以下员工表单状态为processing,8级(总经理)状态为approvedEmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);Employee employee = employeeDao.selectById(form.getEmployeeId());if(employee.getLevel() == 8){form.setState("approved");}else{form.setState("processing");}LeaveFormDao leaveFormDao = sqlSession.getMapper(LeaveFormDao.class);leaveFormDao.insert(form);//2.增加第一条流程数据,说明表单已提交,状态为completeProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);ProcessFlow flow1 = new ProcessFlow();flow1.setFormId(form.getFormId());flow1.setOperatorId(employee.getEmployeeId());flow1.setAction("apply");flow1.setCreateTime(new Date());flow1.setOrderNo(1);flow1.setState("complete");flow1.setIsLast(0);processFlowDao.insert(flow1);//3.分情况创建其余流程数据//3.1 7级以下员工,生成部门经理审批任务,请假时间大于72小时,还需生成总经理审批任务if(employee.getLevel() < 7){Employee dmanager = employeeDao.selectLeader(employee);ProcessFlow flow2 = new ProcessFlow();flow2.setFormId(form.getFormId());flow2.setOperatorId(dmanager.getEmployeeId());flow2.setAction("audit");flow2.setCreateTime(new Date());flow2.setOrderNo(2);flow2.setState("process");long diff = form.getEndTime().getTime() - form.getStartTime().getTime();float hours = diff/(1000*60*60) * 1f;if(hours >= BussinessConstants.MANAGER_AUDIT_HOURS){flow2.setIsLast(0);processFlowDao.insert(flow2);Employee manager = employeeDao.selectLeader(dmanager);ProcessFlow flow3 = new ProcessFlow();flow3.setFormId(form.getFormId());flow3.setOperatorId(manager.getEmployeeId());flow3.setAction("audit");flow3.setCreateTime(new Date());flow3.setState("ready");flow3.setOrderNo(3);flow3.setIsLast(1);processFlowDao.insert(flow3);}else {flow2.setIsLast(1);processFlowDao.insert(flow2);}}else if(employee.getLevel() == 7){ //部门经理//3.2 7级员工,生成总经理审批任务Employee manager = employeeDao.selectLeader(employee);ProcessFlow flow = new ProcessFlow();flow.setFormId(form.getFormId());flow.setOperatorId(manager.getEmployeeId());flow.setAction("audit");flow.setCreateTime(new Date());flow.setState("process");flow.setOrderNo(2);flow.setIsLast(1);processFlowDao.insert(flow);}else if(employee.getLevel() == 8){//3.3 8级员工,生成总经理审批任务,系统自动通过ProcessFlow flow = new ProcessFlow();flow.setFormId(form.getFormId());flow.setOperatorId(employee.getEmployeeId());flow.setAction("audit");flow.setResult("approved");flow.setReason("自动通过");flow.setCreateTime(new Date());flow.setAuditTime(new Date());flow.setState("complete");flow.setOrderNo(2);flow.setIsLast(1);processFlowDao.insert(flow);}return form;});return savedForm;}
}
然后在com.ql.oa.controller包下创建LeaveFormServlet并实现请假申请控制器:
@WebServlet(name = "LeaveFormServlet",urlPatterns = "/leave/*")
public class LeaveFormServlet extends HttpServlet {private LeaveFormService leaveFormService = new LeaveFormService();private Logger logger = LoggerFactory.getLogger(LeaveFormServlet.class);protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");// http://localhost/leave/createString uri = request.getRequestURI();String methodName = uri.substring(uri.lastIndexOf("/")+1);if(methodName.equals("create")){this.create(request,response);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request,response);}/*** 创建请假单* @param request* @param response* @throws ServletException* @throws IOException*/private void create(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收各项请假单数据HttpSession session = request.getSession();User user = (User)session.getAttribute("login_user");String formType = request.getParameter("formType");String strStartTime = request.getParameter("startTime");String strEndTime = request.getParameter("endTime");String reason = request.getParameter("reason");SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH");Map result = new HashMap();try {LeaveForm form = new LeaveForm();form.setEmployeeId(user.getEmployeeId());form.setStartTime(sdf.parse(strStartTime));form.setEndTime(sdf.parse(strEndTime));form.setFormType(Integer.parseInt(formType));form.setReason(reason);form.setCreateTime(new Date());//2. 调用业务逻辑方法leaveFormService.createLeaveForm(form);result.put("code", "0");result.put("message", "success");} catch (Exception e) {logger.error("请假申请异常" ,e);result.put("code", e.getClass().getSimpleName());result.put("message", e.getMessage());}//3. 组织响应数据String json = JSON.toJSONString(result);response.getWriter().println(json);}
}
完整实现请假申请功能
在com.ql.oa.controller下新增ForwardServlet.java,实现页面跳转到对应的ftl文件
package com.ql.oa.controller;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 页面跳转Servlet*/
@WebServlet(name = "ForwardServlet" , urlPatterns = "/forward/*")
public class ForwardServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String uri = request.getRequestURI();/** /forward/form* /forward/a/b/c/form*/String subUri = uri.substring(1);String page = subUri.substring(subUri.indexOf("/"));request.getRequestDispatcher(page + ".ftl").forward(request,response);}
}
然后在webapp\resources路径下引入sweetalert2.all.min.js弹窗JS插件。
然后在src/main/webapp/WEB-INF/ftl下创建form.ftl请假表单申请页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>请假申请</title><link rel="stylesheet" href="/resources/layui/css/layui.css"><style>/*表单容器*/.ns-container {position: absolute;width: 500px;height: 450px;top: 150px;left: 50%;margin-left: -250px;padding: 20px;box-sizing: border-box;border: 1px solid #cccccc;}</style>
</head>
<body>
<div class="layui-row"><blockquote class="layui-elem-quote"><h2>请假申请</h2></blockquote><table id="grdNoticeList" lay-filter="grdNoticeList"></table>
</div>
<div class="ns-container"><h1 style="text-align: center;margin-bottom: 20px">请假申请单</h1><form class="layui-form"><!--基本信息--><div class="layui-form-item"><label class="layui-form-label">部门</label><div class="layui-input-block"><div class="layui-col-md12" style="padding-top: 10px;">${current_department.departmentName}</div></div></div><div class="layui-form-item"><label class="layui-form-label">申请人</label><div class="layui-input-block"><div class="layui-col-md12" style="padding-top: 10px;">${current_employee.name}[${current_employee.title}]</div></div></div><!--请假类型下拉框--><div class="layui-form-item"><label class="layui-form-label">请假类别</label><div class="layui-input-block layui-col-space5"><select name="formType" lay-verify="required" lay-filter="cityCode"><option value="1">事假</option><option value="2">病假</option><option value="3">工伤假</option><option value="4">婚嫁</option><option value="5">产假</option><option value="6">丧假</option></select></div></div><!--请假时长日期选择框--><div class="layui-form-item"><label class="layui-form-label">请假时长</label><div class="layui-input-block layui-col-space5"><input name="leaveRange" type="text" class="layui-input" id="daterange" placeholder=" - " autocomplete="off"><input id="startTime" name="startTime" type="hidden"><input id="endTime" name="endTime" type="hidden"></div></div><!--请假事由--><div class="layui-form-item"><label class="layui-form-label">请假事由</label><div class="layui-input-block layui-col-space5"><input name="reason" type="text" lay-verify="required|mobile" placeholder="" autocomplete="off" class="layui-input"></div></div><!--提交按钮--><div class="layui-form-item " style="text-align: center"><button class="layui-btn" type="button" lay-submit lay-filter="sub">立即申请</button></div></form>
</div><script src="/resources/layui/layui.js"></script>
<!--Sweetalert2对话框-->
<script src="/resources/sweetalert2.all.min.js"></script><script>var layDate = layui.laydate; //Layui日期选择框JS对象var layForm = layui.form; //layui表单对象var $ = layui.$; //jQuery对象//日期时间范围layDate.render({elem: '#daterange',type: 'datetime',range: true,format: 'yyyy年M月d日H时',done: function(value, start, end){//选择日期后触发事件,设置startTime与endTime隐藏域var startTime = start.year + "-" + start.month + "-" + start.date + "-" + start.hours;var endTime = end.year + "-" + end.month + "-" + end.date + "-" + end.hours;console.info("请假开始时间",startTime);$("#startTime").val(startTime);console.info("请假结束时间",endTime);$("#endTime").val(endTime);}});//表单提交事件layForm.on('submit(sub)', function(data){console.info("向服务器提交的表单数据",data.field);$.post("/leave/create",data.field,function (json) {console.info("服务器返回数据",json);if(json.code == "0"){/*SweetAlert2确定对话框*/swal({type: 'success',html: "<h2>请假单已提交,等待上级审批</h2>",confirmButtonText: "确定"}).then(function (result) {window.location.href="/forward/notice";});}else{swal({type: 'warning',html: "<h2>" + json.message + "</h2>",confirmButtonText: "确定"});}},"json");return false;});</script>
</body>
</html>
然后打开navicat,打开sys_node表把菜单url填充,并打开index.ftl文件把菜单跳转路径改成动态的。
<!--子节点-->
<dd class="function" data-parent-id="${node.parentId}"><a href="${node.url}" target="ifmMain">${node.nodeName}</a>
</dd>
运行项目,登录后点击请假申请测试。
Java项目(一)--MyBatis实现OA系统项目实战(7)--开发多级审批流程相关推荐
- JAVA计算机毕业设计园林公司OA系统Mybatis+系统+数据库+调试部署
JAVA计算机毕业设计园林公司OA系统Mybatis+系统+数据库+调试部署 JAVA计算机毕业设计园林公司OA系统Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...
- 开源项目推荐-私人网盘系统项目
开源项目推荐-私人网盘系统项目 参考网址: https://mp.weixin.qq.com/s/9QzQBAwf2f57PAuBZw6PXg 许多程序员都想搭建一个个人网盘,今天就和大家推荐一个备受 ...
- 电子政务源代码java_基于jsp的电子政务系统项目-JavaEE实现电子政务系统项目 - java项目源码...
基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的电子政务系统项目, 该项目可用各类java课程设计大作业中, 电子政务系统项目的系统架构分为前后台两部分, 最终实 ...
- java开发oa系统的目的_JAVA开发的OA系统价值体现
根据目前的OA市场,PHP和JAVA各自为政,PHP开发的OA产品主要是用于低价战,但JAVA开发的OA产品大部分集中在高价战.导致产品价格的关键因素:PHP门槛非常低,程序员数量也很多,再通过PHP ...
- 开源OA:手把手教你搭建OA办公系统(3)开发企业报销审批流程
需求 今天以OA系统中的报销审批流程为例来讲一下流程应用管理.首先介绍一下报销流程的需求,主要分为两部分,流程和表单. 流程 OA的报销流程部分,我们将其分成两种情况:报销金额<=3000元时, ...
- OA系统二十四:请假审批五:【点击“审批”后的审批弹出框】的后台逻辑;(审批结果提交的Dao层和Service层逻辑)
本篇博客的主要内容是:[请假审批内嵌页面],[审批弹出框]的点击"确认提交"后,后台的逻辑:主要是Dao层和Service层这些后台逻辑: 说明: (1)目前来看,为了实现某个功 ...
- OA系统如何实现严谨的费用报销流程
在企业中,会遇到很多报销流程,例如:差旅费报销.日常办公费用.税费支出等等.多种复杂类型报销,领导很难在忙碌的状态下还能妥善管理资金流转,往往是力不从心.为此,很多企业开始利用管理软件来规范报销流程. ...
- 开源OA:手把手教你搭建OA办公系统(4)搭建报销审批流程
O2OA拖曳式流程图开发 新建默认流程 首先我们修改流程名字为"报销审批流程",然后按照需求把所有的节点活动先拖过来,分别修改一下名字 接下来就要画上面的路由了,双击活动节点出现路 ...
- java多级审批流程_[SharePoint 工作流] 如何设计一个通用的多级多审核工作流程(三):工作流开发...
在上2篇博客中,我们有了工作流定义的列表,也有了关联表单和启动表单,现在就是开始开发这个通用工作流的时刻了. 工作流的基本构成就是:一个While循环控制工作流的运转,While里的Task Repl ...
最新文章
- Struts2.3+Spring4.0
- Asp.net网站的ClickOnce自动部署(2)-虚拟目录的配置
- IE6-IE9兼容性问题列表及解决办法_补充之五:在IE9下, disabled的文本框内容被选中后,其他控件无法获得焦点问题...
- STM32一种基于NTC的控温电路及软件实现
- 自学Python6个月,找到了月薪8K的工作,多亏了这套学习方式
- java非侵入式接口实现,C++编写非侵入式接口
- VirusTotal 共享8000万勒索软件样本分析数据库
- [CSS3]Clearfix
- window下安装sonar
- php短信报警直到响应,Cacti实现短信报警
- Python,折线图,手写数字,图像反色、二值化、28X28
- 对于企业是云服务器划算还是自购服务器划算?
- 学习WEB前端第四天(3)-背景图像
- 作业周转时间以及平均等待时间
- 养成好习惯,戒掉坏习惯
- RabbitMQ原理名词解释
- 模板引擎ejs与html,后台模板引擎ejs与前台模板引擎artTemplate的简单介绍
- 计算机软件大赛征稿,全国多媒体教育软件大奖赛征稿函
- phpword html转word word转html
- rabbitmq消费者“无故消失”