需求
流程繪製
一、配置流程
在流程工具類ActUtils.java中配置(添加)流程信息
二、在前臺leaveList頁面添加使用流程的觸發事件(提交按鈕)
三、編寫代碼【本文僅針對流程(提交事件),其他功能此處不做詳細說明】
1、觸發事件(啓動流程)
(1)業務的controller
/* 發起流程: 提交按鈕的觸發事件 */
@RequiresPermissions("flow:leave:start")
@RequestMapping(value = "start")
public String start(String ids, RedirectAttributes redirectAttributes)
throws Exception {
String idArray[] = ids.split(",");
for (String id : idArray) {
leaveService.start(leaveService.get(id));
}
addMessage(redirectAttributes, "提交請假申請成功");
return "redirect:" + Global.getAdminPath() + "/flow/leave/?repage";
}
(2)業務的service
public void start(Leave leave) {
leave.preUpdate();
Map<String,Object> vars = Maps.newHashMap();
System.out.println(UserUtils.getRoleList());
vars.put("user0",UserUtils.getUser().getLoginName()); //重新調整的發起人
for (int i = 0; i < UserUtils.getRoleList().size(); i++) {
if(UserUtils.getRoleList().get(i).getId().contains("c7de52dc20ea43ccafea3db315197c52")){
//部門領導
leave.setState("2"); // 改變狀態:改爲公司領導審批
vars.put("roleType","leader");
}else{
leave.setState("1"); // 改變狀態:改爲部門領導審批
//普通員工
vars.put("roleType","staff"); //不同環節的流程
vars.put("user1",userDao.searchLeader(leave.getOfficeBy().getId(),leave.getCompanyBy().getId(),"depar"
+ "tment").getLoginName()); //部門領導
}
}
dao.update(leave);
vars.put("user2",userDao.searchLeader(leave.getCompanyBy().getId(),leave.getCompanyBy().getId(),"administration").getLoginName());//公司領導
Taskuser taskuser=new Taskuser();//任務分配
taskuser.setTaskindex("leave");// 任務分配中的 標識名
List<Taskuser> list=taskuserService.findList(taskuser);
for(Taskuser taskusers:list){
vars.put(taskusers.getTaskver(),taskusers.getExauser().getLoginName());
}
//開啓流程
actTaskService.startProcess(ActUtils.PD_Leave[0],ActUtils.PD_Leave[1],leave.getId(),UserUtils.getUser().getName()+"|"+UserUtils.getUser().getOffice(),vars);
}
(3)流程的Service(jeeplus框架自帶)
2、審覈環節(需要注意的是流程開啓後每個環節都要帶上流程信息)
(1)前臺界面(需要注意的已用截圖標註)
①:流程信息的攜帶
②流程詳情的回顯
③不同環節的提示(四的實操中可看具體效果)
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ include file="/webpage/include/taglib.jsp"%>
<html>
<head>
<title>審覈界面</title>
<meta name="decorator" content="default" />
<script type="text/javascript" src="${ctxStatic}/webuploader-0.1.5/imageupload.js.jsp"></script>
<script type="text/javascript">
var validateForm;
function doSubmit() {//回調函數,在編輯和保存動作時,供openDialog調用提交表單。
if (validateForm.form()) {
$("#inputForm").submit();
return true;
}
return false;
}
$(document).ready(
function() {
$("#text1").html(tohtml($("#haltreason").val()));
$("#text2").html(tohtml($("#auditopinion").val()));
$("#text3").html(tohtml($("#ratifyopinion").val()));
$("#text4").html(tohtml($("#remarks").val()));
function tohtml(text) {
var img = "";
if (text == "") {
return null;
} else {
if (text.indexOf("|") == -1) {
return "<p> "
+ text + "</p>";
} else if (text.split('|')[0] == "同意") {
img = "<img src=\"../../../userfiles/1/images/同意.png\" style=\"height:45px;width:120px;margin-top:-63px;filter:alpha(opacity=60);-moz-opacity:0.6;-khtml-opacity:0.6;opacity:0.6;\">"
return "<p> "
+ text.split('|')[1]
+ "</p><p style=\"text-align:right;\">"
+ text.split('|')[2]
+ " <br/>"
+ text.split('|')[3]
+ "<br/>"
+ img + "</p>";
} else if (text.split('|')[0] == "不同意") {
img = "<img src=\"../../../userfiles/1/images/不同意.png\" style=\"height:45px;width:80px;margin-right:18px;margin-top:-63px;filter:alpha(opacity=60);-moz-opacity:0.6;-khtml-opacity:0.6;opacity:0.6;\">"
return "<p> "
+ text.split('|')[1]
+ "</p><p style=\"text-align:right;\">"
+ text.split('|')[2]
+ " <br/>"
+ text.split('|')[3]
+ "<br/>"
+ img + "</p>";
}
}
}
var Max = [ $("#text1").height(), $("#text2").height() ];
for (var i = 1; i < Max.length; i++) {
if (Max[i] > Max[0]) {
Max[0] = Max[i];
}
}
$("#text1").height(Max[0]);
$("#text2").height(Max[0]);
$("#text3").height(Max[0]);
$("#text4").height(Max[0]);
validateForm = $("#inputForm").validate(
{
submitHandler : function(form) {
loading('正在提交,請稍等...');
form.submit();
},
errorContainer : "#messageBox",
errorPlacement : function(error, element) {
$("#messageBox").text("輸入有誤,請先更正。");
if (element.is(":checkbox")
|| element.is(":radio")
|| element.parent().is(
".input-append")) {
error.appendTo(element.parent()
.parent());
} else {
error.insertAfter(element);
}
}
});
});
</script>
</head>
<body class="gray-bg">
<form:form id="inputForm" modelAttribute="leave"
action="${ctx}/flow/leave/saveAudit" method="post"
class="form-horizontal">
<form:hidden path="id" />
<form:hidden path="act.taskId" />
<form:hidden path="act.taskName" />
<form:hidden path="act.taskDefKey" />
<form:hidden path="act.procInsId" />
<form:hidden path="act.procDefId" />
<sys:message content="${message}" />
<div class="row">
<div class="col-sm-9">
<div class="wrapper wrapper-content animated fadeInUp">
<div class="ibox">
<div class="ibox-content">
<div class="row">
<div class="col-sm-12">
<div class="m-b-md">
<dd style="text-align:center;">
<span><h2>請假申請</h2></span>
</dd>
</div>
</div>
</div>
<div class="row m-t-sm">
<div class="col-sm-12">
<div class="panel blank-panel">
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane active" id="tab-1">
<table
class="table table-bordered table-condensed dataTables-example dataTable no-footer">
<tbody>
<tr>
<td class="width-15 active"><label class="pull-right">開始時間:</label></td>
<td class="width-35">
<input id="startTime" name="startTime" type="text" maxlength="20" class="laydate-icon form-control layer-date "
value="<fmt:formatDate value="${leave.startTime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/>
</td>
<td class="width-15 active"><label class="pull-right">截止時間:</label></td>
<td class="width-35">
<input id="endTime" name="endTime" type="text" maxlength="20" class="laydate-icon form-control layer-date "
value="<fmt:formatDate value="${leave.endTime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/>
</td>
</tr>
<tr>
<td class="width-15 active"><label class="pull-right">天數:</label></td>
<td class="width-35">
<form:input path="Days" htmlEscape="false" class="form-control "/>
</td>
<td class="width-15 active"><label class="pull-right">事由:</label></td>
<td class="width-35">
<form:input path="Reason" htmlEscape="false" class="form-control "/>
</td>
</tr>
</tbody>
</table>
<act:histoicFlow procInsId="${leave.act.procInsId}" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="wrapper wrapper-content project-manager">
<c:choose>
<c:when test="${leave.act.taskDefKey eq 'testtask-0' }">
<h4>調整結果</h4>
<div class="col-sm-12">
<input id="flag1" name="act.flag" type="radio" class="i-checks required" value="yes" checked/><label>重新申請</label> <input id="flag2" name="act.flag" type="radio" class="i-checks required" value="no"/><label>放棄申請</label>
</div>
<h4>備註</h4>
</c:when>
<c:otherwise>
<h4>審批結果</h4>
<div class="col-sm-12">
<input id="flag1" name="act.flag" type="radio" class="i-checks required" value="yes" checked/><label>同意</label> <input id="flag2" name="act.flag" type="radio" class="i-checks required" value="no"/><label>不同意</label>
</div>
<h4>您的意見</h4>
</c:otherwise>
</c:choose>
<div class="col-sm-12">
<form:textarea path="act.comment" class="required" rows="5" maxlength="255" cssClass="form-control "/><br/>
<input id="btnSubmit" class="btn btn-primary" type="submit" value="提交" />
<button class="btn btn-default" data-toggle="tooltip" data-placement="left" type="button" onclick="history.go(-1)" title="返回">返回</button>
</div>
</div>
</div>
</div>
</form:form>
</body>
</html>
(2)業務代碼
①controller
@RequestMapping(value = "saveAudit")
public String saveAudit(Leave leave,Model model) throws Exception {
if("testtask-0".equals(leave.getAct().getTaskDefKey())){
}else{
if ("no".equals(leave.getAct().getFlag()) && StringUtils.isBlank(leave.getAct().getComment())){
addMessage(model, "請填寫審覈意見。");
return form(leave, model);
}
}
leaveService.saveAudit(leave);
return "redirect:" + adminPath + "/act/task/todo/";
}
②Service
//保存審批
public void saveAudit(Leave leave){
if(StringUtils.isBlank(leave.getId())){
}
// 設置意見
leave.getAct().setComment(("yes".equals(leave.getAct().getFlag())?"同意| ":"不同意| ")+leave.getAct().getComment());
leave.preUpdate();
// 對不同環節的業務邏輯進行操作
String taskDefKey = leave.getAct().getTaskDefKey();
//獲取當前任務編號
String taskId = leave.getAct().getTaskId();
//獲取當前流程實例
String procInsId = leave.getAct().getProcInsId();
//獲取態度
String flag = leave.getAct().getFlag();
//獲取意見
String comment = leave.getAct().getComment();
// 審覈環節testtask-1:部門經理 testtask-2:公司領導
if ("testtask-1".equals(taskDefKey)){
if("yes".equals(flag)){
leave.setState("2"); //部門經理審覈
}else{
//不同意
leave.setState("5");
}
}else if("testtask-2".equals(taskDefKey)){
if("yes".equals(flag)){
leave.setState("4"); //公司領導審覈
}else{
//不同意
leave.setState("5");
}
}else if("testtask-0".equals(taskDefKey)){
if("yes".equals(flag)){
//發起人的調整
for (int i = 0; i < UserUtils.getRoleList().size(); i++) {
if(UserUtils.getRoleList().get(i).getId().contains("c7de52dc20ea43ccafea3db315197c52")){
//部門領導
leave.setState("2"); // 改變狀態:改爲公司領導審批
}else{
leave.setState("1"); // 改變狀態:改爲部門領導審批
}
}
}else{
//放棄調整
leave.setState("3");
}
}
dao.update(leave);
// 提交流程任務
Map<String, Object> vars = Maps.newHashMap();
vars.put("pass", "yes".equals(leave.getAct().getFlag())? "1" : "0");
actTaskService.complete(taskId, procInsId, comment, vars);
}
3、form表單:可進行增、改、看操作
(1)前臺頁面【同樣包含了流程信息的攜帶與回顯】
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/webpage/include/taglib.jsp"%>
<html>
<head>
<title>請假表單</title>
<meta name="decorator" content="default"/>
<script type="text/javascript">
var validateForm;
function doSubmit(){//回調函數,在編輯和保存動作時,供openDialog調用提交表單。
if(validateForm.form()){
$("#inputForm").submit();
return true;
}
return false;
}
$(document).ready(function() {
validateForm = $("#inputForm").validate({
submitHandler: function(form){
loading('正在提交,請稍等...');
form.submit();
},
errorContainer: "#messageBox",
errorPlacement: function(error, element) {
$("#messageBox").text("輸入有誤,請先更正。");
if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
error.appendTo(element.parent().parent());
} else {
error.insertAfter(element);
}
}
});
laydate({
elem: '#startTime' ,type: 'datetime', //目標元素。由於laydate.js封裝了一個輕量級的選擇器引擎,因此elem還允許你傳入class、tag但必須按照這種方式 '#id .class'
event: 'focus' //響應事件。如果沒有傳入event,則按照默認的click
});
laydate({
elem: '#endTime' ,type: 'datetime', //目標元素。由於laydate.js封裝了一個輕量級的選擇器引擎,因此elem還允許你傳入class、tag但必須按照這種方式 '#id .class'
type:'datetime',
event: 'focus' //響應事件。如果沒有傳入event,則按照默認的click
});
});
</script>
</head>
<body class="hideScroll">
<form:form id="inputForm" modelAttribute="leave" action="${ctx}/flow/leave/save" method="post" class="form-horizontal">
<form:hidden path="id"/>
<form:hidden path="act.taskId"/>
<form:hidden path="act.taskName"/>
<form:hidden path="act.taskDefKey"/>
<form:hidden path="act.procInsId"/>
<form:hidden path="act.procDefId"/>
<sys:message content="${message}"/>
<table class="table table-bordered table-condensed dataTables-example dataTable no-footer">
<tbody>
<tr>
<%-- <td class="width-15 active"><label class="pull-right">備註信息:</label></td>
<td class="width-35">
<form:textarea path="remarks" htmlEscape="false" rows="4" class="form-control "/>
</td> --%>
<td class="width-15 active"><label class="pull-right">開始時間:</label></td>
<td class="width-35">
<input id="startTime" name="startTime" type="text" maxlength="20" class="laydate-icon form-control layer-date "
value="<fmt:formatDate value="${leave.startTime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/>
</td>
<td class="width-15 active"><label class="pull-right">截止時間:</label></td>
<td class="width-35">
<input id="endTime" name="endTime" type="text" maxlength="20" class="laydate-icon form-control layer-date "
value="<fmt:formatDate value="${leave.endTime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/>
</td>
</tr>
<tr>
<td class="width-15 active"><label class="pull-right">天數:</label></td>
<td class="width-35">
<form:input path="Days" htmlEscape="false" class="form-control "/>
</td>
<td class="width-15 active"><label class="pull-right">事由:</label></td>
<td class="width-35">
<form:input path="Reason" htmlEscape="false" class="form-control "/>
</td>
</tr>
</tbody>
</table>
<c:if test="${not empty leave.processInstanceId }">
<act:histoicFlow procInsId="${leave.processInstanceId}"/>
</c:if>
</form:form>
</body>
</html>
(2)後臺:根據不同的業務需求調整不同的頁面
/**
* 查看,增加,編輯請假表單頁面
*/
@RequiresPermissions(value={"flow:leave:view","flow:leave:add","flow:leave:edit"},logical=Logical.OR)
@RequestMapping(value = "form")
public String form(Leave leave, Model model) {
String view = "leaveForm"; //新增or修改
// 查看審批清單
if (StringUtils.isNotBlank(leave.getId())) {
String taskDefKey = leave.getAct().getTaskDefKey();// 環節編號
if ("testtask-1".equals(taskDefKey)) {
if (("1").equals(leave.getState())) {//狀態等於1,等待部門領導審覈
view = "leaveAudit";
} else {
view = "leaveView"; //不是審覈環節,查看詳情即可
}
}else if ("testtask-2".equals(taskDefKey)) {// 審覈環節2【總領導審批】
if (("2").equals(leave.getState())) {//狀態等於2,等待公司領導審覈
view = "leaveAudit";
} else {
view = "leaveView";
}
}else if ("testtask-0".equals(taskDefKey)) {// 發起人重新調整
if (("5").equals(leave.getState())) {//狀態等於5,等待重新提交
view = "leaveAudit";
} else {
view = "leaveView";
}
}
}
model.addAttribute("leave", leave);
return "modules/flow/" + view;
}
四、實操看效果
以普通職員爲例(售前1號)
1、提交申請
2、提交後開啓流程
3、部門領導審覈:售前經理
①售前經理可在自己的待辦任務中進行任務辦理操作
②審覈結果:此處選擇不同意
4、發起人調整申請
①看到自己的申請未通過
②去待辦任務中進行任務辦理操作
③調整申請:重新申請
5、部門領導審覈:同意申請,進入下一環節
6、公司領導申請:也是在待辦任務中進行任務辦理操作,同意申請,進行下一環節
7、流程完畢,發起人可看到流程已通過
五、補充
一些標籤是框架自己的東西,如下圖,可直接按住ctrl+具體標籤,點進去查看具體的內容
1、提交按鈕
包含但不限於對於提交的驗證
2、流程信息的回顯
對應的是具體的界面繪製