JeeSite 工作流Activiti的应用实例
新建流程模型
在线办公-流程管理-模型管理-新建模型
点击“提交”后会立即跳转到“流程在线设计器”页面,请看下一章节
- 在线流程设计器
在线办公流程管理模型管理模型管理编辑
- 整体流程图
- matter属性
- 开始结点
- 办公室审批结点
- 箭线-是
- 箭线-否
- 部门意见结点
个人处理结点
事件完成
2.1 设置流程属性
名称:流程定义名称
描述:流程定义描述
流程标识:流程定义KEY,对应procDefKey,用来标识一个流程
2.2 拖拽形状元素
Start event:开始事件
End entit:结束事件
User task:用户任务活动
Service task:服务任务活动
Exclusive gateway:排它网关通道,只能有一条分支执行,如if else
Parallel gateway:并行网关通道,所有分支一块执行
Enclusive gateway:包含网关通道,执行符合条件的分支
参考:http://www.mossle.com/docs/activiti/#bpmnConstructs
2.3 流程发起人流程变量
在开始节点的属性中设置“流程发起人”变量名:如:apply
这时,任务的参与者可设置${apply},来指定谁发起谁执行
如发起人发起流程,被驳回是,驳回到发起人,可使用方法。
2.4 挂接表单地址
全局表单:新建流程时或活动元素上未设置表单标识时调用的表单,位于开始事件属性中“表单标识”字段,指定表单访问地址。
活动表单:当前步骤使用的表单,使用活动节点属性“表单标识”字段。
2.5 设置参与者
在活动节点属性中找到“参与者”属性,点击“…”弹出如下窗口
assignee:任务执行人,设置系统中的“登录名”(loginName)。
candidateUsers:任务执行人,多个用逗号“,”隔开。
candidateGroups:任务执行组,多个用逗号“,”隔开,设置系统中的“角色英文名(enname)”。
assignee和candidateUsers的区别是:assignee不需要签收任务,直接可执行任务;candidateUsers为竞争方式分配任务,被指定人待办中都有一条任务,谁先签收谁就获得任务的执行权。
参与者可指定流程变量(EL表达式),动态指定参与者,如:${processer}
2.6 设置流转条件
在流转线的属性中找到“流转条件”,这里,写EL表达式,返回true或false,如:${flag == ‘1’}
2.7 保存流程设计图
工具栏上点击“保存”按钮
这时,任务的参与者可设置${apply},来指定谁发起谁执行
如发起人发起流程,被驳回是,驳回到发起人,可使用方法。
2.8 注意事项
所有编号,如:模型编号、流程编号、活动节点编号,都不允许以数字开头。
3 部署流程
- 部署流程
-启动流程
-信息填报
上步咱们学习了流程设计,产生流程设计图,如何将我们的图部署到系统中并使用呢,请看如下操作:
在线办公流程管理模型管理模型管理部署
接着系统会提示“部署成功”信息,如果提示错误,说明你流程设计图有问题,请检查错误,重新执行部署操作。
另外两种部署方法,通过eclipse插件设计好的流程:
在线办公-流程管理-流程管理-部署流程-选择流程.bpmn.xml
编写并执行ant脚本,启动系统将自动部署
/ jeesite/src/main/resources/act/build.xml。
设置流程分类:在流程管理中直接点击流程分类进行设置。
同一标识流程,部署多次,版本号自动加1
正在运行的流程,再次部署新流程后,正在运行的流程还按照原来流程设置走,再次新建的流程使用新流程走。
- 事件 填报页面
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
<html>
<head>
<title>事件</title>
<meta name="decorator" content="default"/>
<script type="text/javascript">
$(document).ready(function() {
$("#name").focus();
$("#inputForm").validate({
submitHandler: function(form){
lmatterding('正在提交,请稍等...');
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>
<ul class="nav nav-tabs">
<li><a href="${ctx}/matter/mzMatter/">事件列表</a></li>
<li class="active"><a href="${ctx}/matter/mzMatter/form?id=${mzMatter.id}"><shiro:hasPermission name="matter:mzMatter:edit">${not empty mzMatter.id?'修改':'填报'}事件</shiro:hasPermission><shiro:lacksPermission name="matter:mzMatter:edit">查看</shiro:lacksPermission></a></li>
</ul>
<form:form id="inputForm" modelAttribute="mzMatter" action="${ctx}/matter/mzMatter/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"/>
<form:hidden id="flag" path="act.flag"/>
<sys:message content="${message}"/>
<fieldset>
<legend>事件填报</legend>
<table class="table-form">
<tr>
<td class="tit">名称</td><td>
<form:input path="name" htmlEscape="false" maxlength="50"/>
</td>
<td class="tit">发生时间</td>
<td colspan="2"><input name="happenDate" type="text" readonly="readonly" maxlength="20" class="input-medium Wdate "
value="<fmt:formatDate value="${mzMatter.happenDate}" pattern="yyyy-MM-dd HH:mm:ss"/>"
onclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss',isShowClear:false});"/></td>
</tr>
<tr>
<td class="tit">事件内容描述</td>
<td colspan="5">
<form:textarea path="content" class="required" rows="5" maxlength="200" cssStyle="width:500px"/>
</td>
</tr>
<tr>
<td class="tit">类别</td>
<td colspan="2">
<form:select path="category" class="input-xlarge ">
<form:option value="" label=""/>
<form:options items="${fns:getDictList('matter_category')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
</form:select></td>
</tr>
<tr>
<td class="tit">紧急程度</td>
<td>
<form:select path="urgencyLevel" class="input-xlarge ">
<form:option value="" label=""/>
<form:options items="${fns:getDictList('urgency_level')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
</form:select>
</td>
<td class="tit">地区</td><td>
<sys:treeselect id="area" name="area.id" value="${mzMatter.area.id}" labelName="area.name" labelValue="${mzMatter.area.name}"
title="区域" url="/sys/area/treeData" cssClass="required" allowClear="true" notAllowSelectParent="true"/>
</td>
</tr>
<tr>
<td class="tit">详细地址</td>
<td><form:input path="addressDetail" htmlEscape="false" maxlength="100" class="input-xlarge required"/></td>
<td class="tit">备注</td>
<td><form:input path="remarks" htmlEscape="false" maxlength="50"/></td>
</tr>
<tr>
<td class="tit">办公室意见</td>
<td colspan="5">
${mzMatter.officeText}
</td>
</tr>
<tr>
<td class="tit">部门领导意见</td>
<td colspan="5">
${mzMatter.depText}
</td>
</tr>
<tr>
<td class="tit">事件处理意见</td>
<td colspan="5">
${mzMatter.personText}
</td>
</tr>
</table>
</fieldset>
<div class="form-actions">
<shiro:hasPermission name="matter:mzMatter:edit">
<input id="btnSubmit" class="btn btn-primary" type="submit" value="提交事件" onclick="$('#flag').val('yes')"/>
<c:if test="${not empty mzMatter.id}">
<input id="btnSubmit2" class="btn btn-inverse" type="submit" value="销毁事件" onclick="$('#flag').val('no')"/>
</c:if>
</shiro:hasPermission>
<input id="btnCancel" class="btn" type="button" value="返 回" onclick="history.go(-1)"/>
</div>
<c:if test="${not empty mzMatter.id}">
<act:histoicFlow procInsId="${mzMatter.act.procInsId}" />
</c:if>
</form:form>
</body>
</html>
- Controller
package com.thinkgem.jeesite.modules.matter.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import com.thinkgem.jeesite.modules.matter.entity.MzMatter;
import com.thinkgem.jeesite.modules.matter.service.MzMatterService;
/**
* 审批Controller
* @author thinkgem
* @version 2014-05-16
*/
@Controller
@RequestMapping(value = "${adminPath}/matter/mzMatter")
public class MzMatterController extends BaseController {
@Autowired
private MzMatterService mzMatterService;
@ModelAttribute
public MzMatter get(@RequestParam(required=false) String id){//,
// @RequestParam(value="act.procInsId", required=false) String procInsId) {
MzMatter mzMatter = null;
if (StringUtils.isNotBlank(id)){
mzMatter = mzMatterService.get(id);
// }else if (StringUtils.isNotBlank(procInsId)){
// mzMatter = mzMatterService.getByProcInsId(procInsId);
}
if (mzMatter == null){
mzMatter = new MzMatter();
}
return mzMatter;
}
@RequiresPermissions("matter:mzMatter:view")
@RequestMapping(value = {"list", ""})
public String list(MzMatter mzMatter, HttpServletRequest request, HttpServletResponse response, Model model) {
User user = UserUtils.getUser();
if (!user.isAdmin()){
mzMatter.setCreateBy(user);
}
Page<MzMatter> page = mzMatterService.findPage(new Page<MzMatter>(request, response), mzMatter);
model.addAttribute("page", page);
return "modules/matter/matterList";
}
/**
* 申请单填写
* @param mzMatter
* @param model
* @return
*/
@RequiresPermissions("matter:mzMatter:view")
@RequestMapping(value = "form")
public String form(MzMatter mzMatter, Model model) {
String view = "matterForm";
// 查看审批申请单
if (StringUtils.isNotBlank(mzMatter.getId())){//.getAct().getProcInsId())){
// 环节编号
String taskDefKey = mzMatter.getAct().getTaskDefKey();
// 查看工单
if(mzMatter.getAct().isFinishTask()){
view = "matterView";
}
// 修改环节
else if ("modify".equals(taskDefKey)){
view = "matterForm";
}
// 审核环节
else if ("officedo".equals(taskDefKey)){
view = "matterAudit";
// String formKey = "/oa/mzMatter";
// return "redirect:" + ActUtils.getFormUrl(formKey, mzMatter.getAct());
}
// 审核环节2
else if ("depdo".equals(taskDefKey)){
view = "matterAudit";
}
// // 审核环节3
// else if ("audit3".equals(taskDefKey)){
// view = "matterAudit";
// }
// // 审核环节4
// else if ("audit4".equals(taskDefKey)){
// view = "mzMatterAudit";
// }
// 兑现环节
else if ("apply_end".equals(taskDefKey)){
view = "matterAudit";
}
}
model.addAttribute("mzMatter", mzMatter);
return "modules/matter/" + view;
}
/**
* 申请单保存/修改
* @param mzMatter
* @param model
* @param redirectAttributes
* @return
*/
@RequiresPermissions("matter:mzMatter:edit")
@RequestMapping(value = "save")
public String save(MzMatter mzMatter, Model model, RedirectAttributes redirectAttributes) {
if (!beanValidator(model, mzMatter)){
return form(mzMatter, model);
}
mzMatterService.save(mzMatter);
addMessage(redirectAttributes, "提交审批'" + mzMatter.getCurrentUser().getName() + "'成功");
return "redirect:" + adminPath + "/act/task/todo/";
}
/**
* 工单执行(完成任务)
* @param mzMatter
* @param model
* @return
*/
@RequiresPermissions("matter:mzMatter:edit")
@RequestMapping(value = "saveMatter")
public String saveAudit(MzMatter mzMatter, Model model) {
if (StringUtils.isBlank(mzMatter.getAct().getFlag())
|| StringUtils.isBlank(mzMatter.getAct().getComment())){
addMessage(model, "请填写审核意见。");
return form(mzMatter, model);
}
mzMatterService.auditSave(mzMatter);
return "redirect:" + adminPath + "/act/task/todo/";
}
/**
* 删除工单
* @param id
* @param redirectAttributes
* @return
*/
@RequiresPermissions("matter:mzMatter:edit")
@RequestMapping(value = "delete")
public String delete(MzMatter mzMatter, RedirectAttributes redirectAttributes) {
mzMatterService.delete(mzMatter);
addMessage(redirectAttributes, "删除审批成功");
return "redirect:" + adminPath + "/oa/mzMatter/?repage";
}
}
-Service
package com.thinkgem.jeesite.modules.matter.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Maps;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.act.service.ActTaskService;
import com.thinkgem.jeesite.modules.act.utils.ActUtils;
import com.thinkgem.jeesite.modules.matter.entity.MzMatter;
import com.thinkgem.jeesite.modules.matter.dao.MzMatterDao;
import com.thinkgem.jeesite.modules.oa.entity.TestAudit;
/**
* 民宗事件Service
* @author lmm
* @version 2017-05-15
*
*
*/
@Service
@Transactional(readOnly = true)
public class MzMatterService extends CrudService<MzMatterDao, MzMatter> {
@Autowired
private ActTaskService actTaskService;
public MzMatter get(String id) {
return super.get(id);
}
public List<MzMatter> findList(MzMatter mzMatter) {
return super.findList(mzMatter);
}
public Page<MzMatter> findPage(Page<MzMatter> page, MzMatter mzMatter) {
return super.findPage(page, mzMatter);
}
@Transactional(readOnly = false)
public void save(MzMatter mzMatter) {
// 申请发起
if (StringUtils.isBlank(mzMatter.getId())){
mzMatter.preInsert();
dao.insert(mzMatter);
// 启动流程
actTaskService.startProcess(ActUtils.PD_MATTER[0], ActUtils.PD_MATTER[1], mzMatter.getId(), mzMatter.getContent());
}
// 重新编辑申请
else{
mzMatter.preUpdate();
dao.update(mzMatter);
mzMatter.getAct().setComment(("yes".equals(mzMatter.getAct().getFlag())?"[重申] ":"[销毁] ")+mzMatter.getAct().getComment());
// 完成流程任务
Map<String, Object> vars = Maps.newHashMap();
vars.put("pass", "yes".equals(mzMatter.getAct().getFlag())? "1" : "0");
actTaskService.complete(mzMatter.getAct().getTaskId(), mzMatter.getAct().getProcInsId(), mzMatter.getAct().getComment(), mzMatter.getContent(), vars);
}
}
@Transactional(readOnly = false)
public void delete(MzMatter mzMatter) {
super.delete(mzMatter);
}
/**
* 审核审批保存
* @param testAudit
*/
@Transactional(readOnly = false)
public void auditSave(MzMatter mzMatter) {
// 设置意见
mzMatter.getAct().setComment(("yes".equals(mzMatter.getAct().getFlag())?"[同意] ":"[驳回] ")+mzMatter.getAct().getComment());
mzMatter.preUpdate();
// 对不同环节的业务逻辑进行操作
String taskDefKey = mzMatter.getAct().getTaskDefKey();
// 审核环节
if ("officedo".equals(taskDefKey)){
mzMatter.setOfficeText(mzMatter.getAct().getComment());
dao.updateOfficeText(mzMatter);
}
else if ("depdo".equals(taskDefKey)){
mzMatter.setDepText(mzMatter.getAct().getComment());
dao.updateDepText(mzMatter);
}
else if ("apply_end".equals(taskDefKey)){
mzMatter.setPersonText(mzMatter.getAct().getComment());
dao.updatePersonText(mzMatter);
}
// 未知环节,直接返回
else{
return;
}
// 提交流程任务
Map<String, Object> vars = Maps.newHashMap();
vars.put("pass", "yes".equals(mzMatter.getAct().getFlag())? "1" : "0");
actTaskService.complete(mzMatter.getAct().getTaskId(), mzMatter.getAct().getProcInsId(), mzMatter.getAct().getComment(), vars);
// vars.put("var_test", "yes_no_test2");
// actTaskService.getProcessEngine().getTaskService().addComment(testAudit.getAct().getTaskId(), testAudit.getAct().getProcInsId(), testAudit.getAct().getComment());
// actTaskService.jumpTask(testAudit.getAct().getProcInsId(), testAudit.getAct().getTaskId(), "audit2", vars);
}
}
JeeSite 工作流Activiti的应用实例的更多相关文章
- activiti官网实例项目activiti-explorer之扩展流程节点属性2
情景需求:需要查找activiti-explorer项目中获取流程id的方法,然后根据流程id获取相应字段在节点属性中添加内容. 大致流程:拿取整个流程id获取对应表单属性,在页面节点属性中展示对应表 ...
- 工作流Activiti新手入门学习路线整理
写在前面: 最近项目中使用到了工作流,虽然此部分不是自己需要完成的,但是也涉及到了要调用写的接口.正好有时间,就了解下,以便之后能在其他项目中用到时,不至于什么都不知道什么都不了解. 这里就主要整理下 ...
- Activiti的流程实例及挂起激活(七)
1.1什么是流程实例 参与者(可以是用户也可以是程序)按照流程定义内容发起一个流程,这就是一个流程实例.是动态的.流程定义和流程实例的图解: 1.2启动流程实例 流程定义部署在 activiti 后, ...
- Activiti的流程实例【ProcessInstance】与执行实例【Execution】
最近,我在做流程引擎Activiti相关的东西,刚开始时的一个知识点困扰了我许久,那就是Activiti的ProcessInstance与Execution的区别,这是一个Activiti的难点,能够 ...
- activiti会签 多实例例子
在实际的业务中,可能存在存在这么一种情况,当流程运行到某一个环节时,可能需要同时多个人的参与,才可以完成此环节.此时就可以用到activiti的多实例来解决此问题. 一.将一个节点设置成多实例的方法: ...
- jeesite中activiti中的流程表梳理
最近在利用jeesite开发一个小系统,趁着这个机会整理了activiti中的相关表,跟踪流程,然后查看这几个表中数据的变化,可以更好地理解流程的开发.现在整理出来,希望可以帮助更多的人! 表结构 一 ...
- (2)java程序走一遍工作流activiti
工作流从流程定义到创建一个流程实例完成执行步骤 使用activi-designer创建一个流程定义(.bpmn结尾的文件) 将定义好的流程定义和生成的png图片通过RepositoryService( ...
- 工作流——activiti
1.导入依赖 <!-- activiti工作流 --> <dependency> <groupId>org.activiti</groupId> < ...
- activiti整合开发实例总结
参考手册:http://www.mossle.com/docs/activiti/ 一.applicationContext.xml中引入activiti相关配置的xml文件 <!-- begi ...
随机推荐
- HDU 5973 Game of Taking Stones (威佐夫博弈+高精度)
题意:给定两堆石子,每个人可以从任意一堆拿任意个,也可以从两堆中拿相同的数量,问谁赢. 析:直接运用威佐夫博弈,floor(abs(a, b) * (sqrt(5)+1)/2) == min(a, b ...
- C# BackgroundWorker(异步线程)
日期:2018年11月28日 环境:Windows 10,VS2015 前言 .NET 类库中提供了一个快捷使用多线程的帮助类BackgroundWorker,能够快速创建一个新的线程,并能报告进度 ...
- windows severs 2008r2 180天激活
无需破解:Windows Server 2008 R2 至少免费使用 900天 1.首先安装后,有一个180天的试用期. 2.在180天试用期即将结束时,使用下面的评估序列号激活Svr 2008 R2 ...
- 算法学习分析-点分治 HDU 6269 Master of Subgraph
首先给出定义 点分治是一种处理树上路径的工具 挂出一道题目来:Master of Subgraph 这道题目让你求所有联通子图加和所能产生数字,问你1到m之间,那些数字可以被产生 这道题目,假如我们利 ...
- 退役or延期退役
究竟是\(150\)天后退役,还是能继续续命呢? 一切看自己了!加油!\(cyh\)!千万不要败在别人的只言片语之下啊!
- 洛谷P3384【模板】树链剖分
题目描述 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): 格式: \(1\) \(x\) \(y\) \(z\) 表示将树从\(x\ ...
- 洛谷P2846 光开关Light Switching
题目描述 灯是由高科技--外星人鼠标操控的.你只要左击两个灯所连的鼠标, 这两个灯,以及之间的灯都会由暗变亮,或由亮变暗.右击两个灯所连的鼠 标,你就可以知道这两个灯,以及之间的灯有多少灯是亮的.起初 ...
- EventLoop-浏览器与Node.js--整理
近来面试中会遇到的问题,关于浏览器和Nodejs两个运行环境的Event loop. 整理值得阅读的优秀文章 参考文章: 1.不要混淆nodejs和浏览器的eventloop 2.nodejs官网关于 ...
- 谈缓存数据库在web开发中的重要性
1.开局先抛出如下问题: ①当关系型数据库存放的数据量很大时,每次查询耗时明显变长,那么如何解决该问题? ②当业务要求单用户登录(即同一个账户有一个用户登录后,第二个用户再登录该账户要么挤出之前的登录 ...
- Jmeter_拦截Excel文件输出流到本地
一般而言,对于页面的“导出”操作,主要经历如下两个操作:①根据数据库的内容,将文件导出到应用服务器上:②将服务器上的文件下载到本地电脑: Jmeter同LoadRunner类似,只能记录服务端与客户端 ...