普通表单——任务列表

来源:互联网 发布:软件企业认定流程 编辑:程序博客网 时间: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}"/>



1 0
原创粉丝点击