普通表单——任务列表
来源:互联网 发布:软件企业认定流程 编辑:程序博客网 时间:2024/05/20 23:03
菜单里有
<a rel="oa/leave/list/task">请假办理(普通)</a>
一看就是任务列表嘛,在列表里选择可办理任务,这一节我们只研究任务列表。
上一节“流程启动”中,我们有一个问题没有讨论,就是流程实例、TASK和IDENTITY之间的关系
这里是流程启动之后,数据库中ACT_RU_TASK表的数据
可以看到流程实例当前任务进行到了部门领导审批,这是紧跟着开始节点的下一个用户任务。
TASK_DEF_KEY_和NAME_是在bpmn中指定的。
<userTask id="deptLeaderAudit" name="部门领导审批" activiti:candidateGroups="deptLeader"></userTask>
ACT_RU_IDENTITYLINK表中的数据
所谓IDENTITY在activiti中其实就是用户或者组,对应user_id和group_id,ACT_RU_IDENTITYLINK表记录对象和任务或流程实例的关系。
ACT_RU_IDENTITYLINK表有一个字段"TYPE_",这个字段用来标明关系的类型。
第一条数据对象类型是starter(发起人),用户ID是kafeitu,发起人是和流程实例有关系的,不属于某个用户任务。
然后是当前任务有关的一个对象,对象类型是candidate(候选人),说明这个任务还没有被签收(claim),指定的是候选组而不是某个用户,这个组ID是deptLeader,这个也是在bpmn中指定的。
签收后对象类型应该是participant,然后USER_ID_字段被更新为签收用户ID。
基本上我们从ACT_RU_IDENTITYLINK表就能知道流程中每个节点和用户权限之间的关系,这也进入了我们任务列表的讨论。
一、控制层
@Controller@RequestMapping(value = "/oa/leave")public class LeaveController { /** * 任务列表 * * @param leave */ @RequestMapping(value = "list/task") public ModelAndView taskList(HttpSession session, HttpServletRequest request) { ModelAndView mav = new ModelAndView("/oa/leave/taskList"); Page<Leave> page = new Page<Leave>(PageUtil.PAGE_SIZE); int[] pageParams = PageUtil.init(page, request); String userId = UserUtil.getUserFromSession(session).getId(); workflowService.findTodoTasks(userId, page, pageParams); mav.addObject("page", page); return mav; }}
二、服务层
/** * 查询待办任务 * * @param userId 用户ID * @return */ @Transactional(readOnly = true) public List<Leave> findTodoTasks(String userId, Page<Leave> page, int[] pageParams) { List<Leave> results = new ArrayList<Leave>(); // 根据当前人的ID查询 TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId); List<Task> tasks = taskQuery.list(); // 根据流程的业务ID查询实体并关联 for (Task task : tasks) { String processInstanceId = task.getProcessInstanceId(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult(); String businessKey = processInstance.getBusinessKey(); if (businessKey == null) { continue; } Leave leave = leaveManager.getLeave(new Long(businessKey)); leave.setTask(task); leave.setProcessInstance(processInstance); leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId())); results.add(leave); } page.setTotalCount(taskQuery.count()); page.setResult(results); return results; }
/** * 查询流程定义对象 * * @param processDefinitionId 流程定义ID * @return */ protected ProcessDefinition getProcessDefinition(String processDefinitionId) { ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); return processDefinition; }
--- starting TaskQueryImpl --------------------------------------------------------
Preparing: select distinct RES.* from ACT_RU_TASK RES left join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ WHERE (RES.ASSIGNEE_ = ? or (RES.ASSIGNEE_ is null and (I.USER_ID_ = ? or I.GROUP_ID_ IN (select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = ? ) ) ) ) order by RES.ID_ asc LIMIT ? OFFSET ?
Parameters: leaderuser(String), leaderuser(String), leaderuser(String), 2147483647(Integer), 0(Integer)
--- TaskQueryImpl finished --------------------------------------------------------
--- starting ProcessInstanceQueryImpl --------------------------------------------------------
Preparing: select distinct RES.* , P.KEY_ as ProcessDefinitionKey, P.ID_ as ProcessDefinitionId from ACT_RU_EXECUTION RES inner join ACT_RE_PROCDEF P on RES.PROC_DEF_ID_ = P.ID_ WHERE RES.PARENT_ID_ is null and RES.ID_ = ? and RES.PROC_INST_ID_ = ? and (RES.SUSPENSION_STATE_ = 1) order by RES.ID_ asc LIMIT ? OFFSET ?
Parameters: 12(String), 12(String), 2147483647(Integer), 0(Integer)
--- ProcessInstanceQueryImpl finished --------------------------------------------------------
--- starting ProcessDefinitionQueryImpl --------------------------------------------------------
Preparing: select distinct RES.* from ACT_RE_PROCDEF RES WHERE RES.ID_ = ? order by RES.ID_ asc LIMIT ? OFFSET ?
Parameters: leave:1:20(String), 2147483647(Integer), 0(Integer)
--- ProcessDefinitionQueryImpl finished --------------------------------------------------------
--- starting ProcessInstanceQueryImpl --------------------------------------------------------
Preparing: select distinct RES.* , P.KEY_ as ProcessDefinitionKey, P.ID_ as ProcessDefinitionId from ACT_RU_EXECUTION RES inner join ACT_RE_PROCDEF P on RES.PROC_DEF_ID_ = P.ID_ WHERE RES.PARENT_ID_ is null and RES.ID_ = ? and RES.PROC_INST_ID_ = ? and (RES.SUSPENSION_STATE_ = 1) order by RES.ID_ asc LIMIT ? OFFSET ?
Parameters: 25(String), 25(String), 2147483647(Integer), 0(Integer)
--- ProcessInstanceQueryImpl finished --------------------------------------------------------
--- starting ProcessDefinitionQueryImpl --------------------------------------------------------
Preparing: select distinct RES.* from ACT_RE_PROCDEF RES WHERE RES.ID_ = ? order by RES.ID_ asc LIMIT ? OFFSET ?
Parameters: leave:1:20(String), 2147483647(Integer), 0(Integer)
--- ProcessDefinitionQueryImpl finished --------------------------------------------------------
--- starting TaskQueryImpl --------------------------------------------------------
Preparing: select count(distinct RES.ID_) from ACT_RU_TASK RES left join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ WHERE (RES.ASSIGNEE_ = ? or (RES.ASSIGNEE_ is null and (I.USER_ID_ = ? or I.GROUP_ID_ IN (select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = ? ) ) ) )
Parameters: leaderuser(String), leaderuser(String), leaderuser(String)
--- TaskQueryImpl finished --------------------------------------------------------
可以看到,taskService.createTaskQuery().taskCandidateOrAssigned(userId)实际执行的SQL为
SELECT DISTINCT RES.* FROM ACT_RU_TASK RES LEFT JOIN ACT_RU_IDENTITYLINK I ON I.TASK_ID_ = RES.ID_ WHERE ( RES.ASSIGNEE_ = 'leaderuseror' OR ( RES.ASSIGNEE_ IS NULL AND ( I.USER_ID_ = 'leaderuser ' OR I.GROUP_ID_ IN (SELECT g.GROUP_ID_ FROM ACT_ID_MEMBERSHIP g WHERE g.USER_ID_ = 'leaderuser') ) ) ) ORDER BY RES.ID_ ASC LIMIT 2147483647 OFFSET 0
activiti本身还实现了一些别的查询API,如:
taskService.createTaskQuery().taskCandidateGroup(groupId); // 查询候选组的任务
三、页面
<table width="100%" class="need-border"><thead><tr><th>假种</th><th>申请人</th><th>申请时间</th><th>开始时间</th><th>结束时间</th><th>当前节点</th><th>任务创建时间</th><th>流程状态</th><th>操作</th></tr></thead><tbody><c:forEach items="${page.result }" var="leave"><c:set var="task" value="${leave.task }" /><c:set var="pi" value="${leave.processInstance }" /><tr id="${leave.id }" tid="${task.id }"><td>${leave.leaveType }</td><td>${leave.userId }</td><td>${leave.applyTime }</td><td>${leave.startTime }</td><td>${leave.endTime }</td><td><a class="trace" href='#' pid="${pi.id }" pdid="${pi.processDefinitionId}" title="点击查看流程图">${task.name }</a></td><%--<td><a target="_blank" href='${ctx }/workflow/resource/process-instance?pid=${pi.id }&type=xml'>${task.name }</a></td> --%><td>${task.createTime }</td><td>${pi.suspended ? "已挂起" : "正常" };<b title='流程版本号'>V: ${leave.processDefinition.version }</b></td><td><c:if test="${empty task.assignee }"><a class="claim" href="${ctx }/oa/leave/task/claim/${task.id}">签收</a></c:if><c:if test="${not empty task.assignee }"><%-- 此处用tkey记录当前节点的名称 --%><a class="handle" tkey='${task.taskDefinitionKey }' tname='${task.name }' href="#">办理</a></c:if></td></tr></c:forEach></tbody></table><tags:pagination page="${page}" paginationSize="${page.pageSize}"/>
- 普通表单——任务列表
- 普通表单——流程启动
- android入门——对话框(普通、列表带图标或普通列表、单选、多选)
- 表单美化——下拉列表
- 列表标签、表单标签—实验
- web前端—列表和表单
- HTML常用标签(一)——表单控件&列表
- html5基础知识(2)-——表格&&列表&&表单
- Ubuntu普通任务
- Android之——获取进程总数、内存、任务列表
- vs中的视图—任务列表的使用问题
- VS技巧—任务列表Task List(ToDoList)
- jquerymobile普通列表事例
- html普通列表
- Google普通权限列表
- AlertDialog的普通列表
- BroadcastReceiver—普通广播
- php ajax提交普通表单
- WinDebug dump
- android 引导页 红点 岁页面滑动儿滑动
- php stdClass var_export
- uploadify3.2.1+struts 使用及问题总结
- IRQL深入解析(1)--IRQL级别
- 普通表单——任务列表
- HTTPS精要
- 原生js添加删除class
- Eclipse添加freemarker插件
- service receive keyevent
- iOS开发 改变UINavigationController的UINavigationBar的高度和背景图片
- 疑问 jsp里边写的js和引入的js有差别
- 浙江大学PAT_乙级_1017. A除以B (20)
- 百度地图不用手动描点获取行政区域边界